TypeInterceptor Implementation in StructureMap 4.6 - structuremap

Can someone help me to convert the below line of code from StructureMap 2.6 to Structure Map 4.6
public class EventAggregatorInterceptor : TypeInterceptor
{
public object Process(object target, IContext context)
{
IEventPublisher eventPublisher = context.GetInstance<IEventPublisher>();
eventPublisher.RegisterHandlers(target);
return target;
}
public bool MatchesType(Type type)
{
bool matchesType = type.ImplementsInterfaceTemplate(typeof(IEventHandler<>));
return matchesType;
}
}
I will appreciate any help

I got it working, below is the code
public class EventListenerRegistration : IInterceptorPolicy
{
public string Description
{
get
{
return "Adds the constructed object to the EventAggregator";
}
}
public IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance)
{
if (instance.ReturnedType.FindInterfacesThatClose(typeof(IEventHandler<>)).Any())
{
Expression<Action<IContext, object>> register = (c, o) => c.GetInstance<IEventPublisher>().RegisterHandlers(o);
yield return new ActivatorInterceptor<object>(register);
}
}
}
And then I register it inside my Registry constructor
Policies.Interceptors(new EventListenerRegistration());

Related

Interface with more implementation and Dependency Injection

I created a project with .net Core 2.
Now I have a List of classes from the same interface which I needed at runtime.
My problem is, I can't add this classes to the servicecollection (only one interface). So I don't have access to the other services in those classes. Also I think it wouldn't solve it.
I could create a singleton/static class with my servicecollection and use the IServiceProvider to get those other services from there, but I think that isn't the best practice.
Here is an example of my problem:
public class Manager : IManager
{
private IList<IMyService> _myService;
public Manager()
{
IList<Type> types = GetIMyServiceTypes();
foreach (Type type in types)
{
var instance = (IMyService)Activator.CreateInstance(type);
_myService.Add(instance)
}
}
public IList<bool> IsTrue()
{
return _myService
.Select(se => se.IsTrue())
.ToList();
}
public IList<Type> GetIMyServiceTypes()
{
var type = typeof(IMyService);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p))
.ToList();
return types;
}
}
public class ServiceType1: IMyService
{
public bool IsTrue()
{
//Need Access to IServiceCollection Services
}
}
public interface IMyService
{
bool IsTrue();
}
public class MyController : Controller
{
private IManager _amanager;
public MyController(IManager manager)
{
_manager = manager
}
public IActionResult IsTrue()
{
IList<bool> isTrue =_manager.IsTrue();
return new ObjectResult(isTrue);
}
}
Is there a pattern, which I could use to solve my problem? Is there a best practice to have access to the services without using them in the constructor?
I found the solution on another post in stackoverflow https://stackoverflow.com/a/44177920/5835745
But I will post my changes for other people with the same problem. I loaded the list of classes from the configuration, but it's also possible to add all classes.
public class Manager : IManager
{
private IList<IMyService> _myService;
private readonly Func<string, IService> _serviceAccessor;
public Manager (Func<string, IService> serviceAccessor)
{
IList<string> authentications = new List<string> {"value1", "value2"}
foreach (string authentication in authentications)
{
AddAuthentication(_serviceAccessor(authentication));
}
}
public IList<bool> IsTrue()
{
return _myService
.Select(se => se.IsTrue())
.ToList();
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<Value1>();
services.AddTransient<Value2>();
services.AddTransient(factory =>
{
Func<string, IService> accesor = key =>
{
switch (key)
{
case "value1":
return factory.GetService<Value1>();
case "value2":
return factory.GetService<Value2>();
default:
throw new KeyNotFoundException();
}
};
return accesor;
});
}
}

Error while creating plugin in Nop Commerce

This is my first demo project in Nopcommerce and i have tried to make my own plugin but during the time of Build some error is seen. Below are some codes.
namespace Nop.Plugin.Aowi.Testimonial.Data
{
public class TestimonialRecordObjectContext : DbContext , IDbContext
{
public TestimonialRecordObjectContext(string nameOrConnectionString) : base(nameOrConnectionString) { }
#region Implementation of IDbContext
#endregion
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new TestimonialRecordMap());
base.OnModelCreating(modelBuilder);
}
public string CreateDatabaseInstallationScript()
{
return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript();
}
public void Install()
{
//It's required to set initializer to null (for SQL Server Compact).
//otherwise, you'll get something like "The model backing the 'your context name' context has changed since the database was created. Consider using Code First Migrations to update the database"
Database.SetInitializer<TestimonialRecordObjectContext>(null);
Database.ExecuteSqlCommand(CreateDatabaseInstallationScript());
SaveChanges();
}
public void Uninstall()
{
var dbScript = "DROP TABLE Testimonial";
Database.ExecuteSqlCommand(dbScript);
SaveChanges();
}
public new IDbSet<TEntity> Set<TEntity>() where TEntity : BaseEntity
{
return base.Set<TEntity>();
}
public System.Collections.Generic.IList<TEntity> ExecuteStoredProcedureList<TEntity>(string commandText, params object[] parameters) where TEntity : BaseEntity, new()
{
throw new System.NotImplementedException();
}
public System.Collections.Generic.IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters)
{
throw new System.NotImplementedException();
}
public int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = null, params object[] parameters)
{
throw new System.NotImplementedException();
}
}
}
This is the Dependency registrar part
namespace Nop.Plugin.Aowi.Testimonial.Infastructure
{
public class DependencyRegistrar: IDependencyRegistrar
{
private const string CONTEXT_NAME ="nop_object_context_product_view_tracker";
public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
{
//data context
this.RegisterPluginDataContext<TestimonialRecordObjectContext>(builder, CONTEXT_NAME);
//override required repository with our custom context
builder.RegisterType<EfRepository<TestimonialRecord>>()
.As<IRepository<TestimonialRecord>>()
.WithParameter(ResolvedParameter.ForNamed<IDbContext>(CONTEXT_NAME))
.InstancePerLifetimeScope();
}
public int Order
{
get { return 1; }
}
}
}
Even after cleaning and Building i am getting this error.
Can anyone help me with this. I have done all of this by watching a tutorial so if anyone can help me correct my mistake i will be really greatful.
You just need to implement this method and properties of IDbContext interface, which are described in error log, in your custom context.
for example, how it is done in one of the existing plugin Tax.CountryStateZip:
public void Detach(object entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
((IObjectContextAdapter)this).ObjectContext.Detach(entity);
}
public virtual bool ProxyCreationEnabled
{
get { return this.Configuration.ProxyCreationEnabled; }
set { this.Configuration.ProxyCreationEnabled = value; }
}
public virtual bool AutoDetectChangesEnabled
{
get { return this.Configuration.AutoDetectChangesEnabled; }
set { this.Configuration.AutoDetectChangesEnabled = value; }
}
I cannot get an idea from your code that where is actual issue. But i suggest by an example.
make your install method code like:
public void Install()
{
//create the table
var dbScript = CreateDatabaseScript();
Database.ExecuteSqlCommand(dbScript);
SaveChanges();
}
Add a new class called EfStartUpTask and paste following code:
public class EfStartUpTask : IStartupTask
{
public void Execute()
{
//It's required to set initializer to null (for SQL Server Compact).
//otherwise, you'll get something like "The model backing the 'your context name' context has changed since the database was created. Consider using Code First Migrations to update the database"
Database.SetInitializer<YourContext>(null);
}
public int Order
{
//ensure that this task is run first
get { return 0; }
}
}
And your DependencyRegistrar :
public class DependencyRegistrar : IDependencyRegistrar
{
public virtual void Register(ContainerBuilder builder, ITypeFinder typeFinder)
{
builder.RegisterType<YourService>().As<YourserviceInterface>().InstancePerLifetimeScope();
//data context
this.RegisterPluginDataContext<YourContext>(builder, "nop_object_context_product_view_tracker");
//override required repository with our custom context
builder.RegisterType<EfRepository<YourEntityClass>>()
.As<IRepository<YourEntityClass>>()
.WithParameter(ResolvedParameter.ForNamed<IDbContext>("nop_object_context_product_view_tracker"))
.InstancePerLifetimeScope();
}
public int Order
{
get { return 1; }
}
}
Note: you have to change YourContext to your context name and same as for entity class
Hope this helps!

How do I use GetAll with Ninject so that one failure doesn't stop the other bindings from resolving?

Some of the provided bindings for the mutli injection may fail to resolve.
public List<IMyCommand> GetMyCommands()
{
//throws
return kernel.GetAll<IMyCommand>().ToList();
}
I want to still get all the successfully resolved objects, and ideally which ones failed. Is there a way to achieve this with Ninject?
Not out of the box.
But we can create some kind of hack/Workaround. Caution. I would rather implement some specific mechanism which handles my case explicitly than to involve Ninject in that.
But for the curiuous minded, here you go:
If you have a look at the implementation of IResolutionRoot.TryGet you'll see that all it does is catch ActivationException and return default(T) in that case.
We can create our own TryGetAll<T> which does the same, but not for the entire IRequest but rather for each binding separately. So here's how to do it:
public static class ResolutionRootExtensions
{
public static IEnumerable<T> TryGetAll<T>(this IResolutionRoot resolutionRoot)
{
var request = resolutionRoot.CreateRequest(
typeof(IFoo),
x => true,
Enumerable.Empty<IParameter>(),
true,
false);
IEnumerable results = resolutionRoot.Resolve(request);
IEnumerator enumerator = results.GetEnumerator();
while (MoveNextIgnoringActivationException(enumerator))
{
yield return (T)enumerator.Current;
}
}
private static bool MoveNextIgnoringActivationException(
IEnumerator enumerator)
{
while (true)
{
try
{
return enumerator.MoveNext();
}
catch (ActivationException)
{
}
}
}
}
I've tested it and it works:
public class Test
{
[Fact]
public void Foo()
{
var kernel = new StandardKernel();
kernel.Bind<IFoo>().To<FooA>();
kernel.Bind<IFoo>().To<FooWithDependencyD>();
kernel.Bind<IFoo>().To<FooB>();
kernel.Bind<IFoo>().To<FooC>();
kernel.Bind<IFoo>().To<FooWithDependencyE>();
kernel.TryGetAll<IFoo>().Should()
.HaveCount(3)
.And.Contain(x => x.GetType() == typeof(FooA))
.And.Contain(x => x.GetType() == typeof(FooB))
.And.Contain(x => x.GetType() == typeof(FooC));
}
}
public interface IFoo
{
}
class FooA : IFoo { }
class FooB : IFoo { }
class FooC : IFoo { }
class FooWithDependencyD : IFoo
{
private readonly IDependency _dependency;
public FooWithDependencyD(IDependency dependency)
{
_dependency = dependency;
}
}
class FooWithDependencyE : IFoo
{
private readonly IDependency _dependency;
public FooWithDependencyE(IDependency dependency)
{
_dependency = dependency;
}
}
internal interface IDependency
{
}

Autofac. How to get caller class Type?

Suppose we have two classes with same constructor Injectable dependency:
public class FirstClass
{
public FirstClass(ISomeDependency someDependency)
{ }
}
public class SecondClass
{
public SecondClass(ISomeDependency someDependency)
{ }
}
Now we have a registration for ISomeDependency:
builder.Register(x =>
{
string key = GetKeyFromCurrentHttpRequest();
// if "Caller" is "FirstClass" return new Dependency(key);
// else return new Dependency("defaultKey");
}).As<ISomeDependency>();
Note: This is a simplified use case. The real scenario is much more complicated.
1. How to get "Caller" type which tryies to resolve ISomeDependency?
2. Is there a better way design for such situations?
You can use delegate factories do achieve your goal. The only drawback is the FirstClass and SecondClass cannot use ISomeDependency as parameter.
You can try this code in a console application (just add Autofac dependency).
using System;
using Autofac;
namespace test
{
class MainClass
{
public static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder ();
builder.RegisterType<SomeDependency>().As<ISomeDependency>();
builder.RegisterType<FirstClass>();
builder.RegisterType<SecondClass>();
var container = builder.Build();
var dummy = container.Resolve<FirstClass>();
var dummy2 = container.Resolve<SecondClass>();
}
public interface ISomeDependency
{
}
public class SomeDependency : ISomeDependency
{
public delegate ISomeDependency Factory(string value);
private readonly string _value;
public SomeDependency(string value)
{
_value = value;
Console.WriteLine("Value = " + _value);
}
}
public class FirstClass
{
private ISomeDependency _dependency;
public FirstClass(SomeDependency.Factory factory)
{
_dependency = factory.Invoke("my value");
}
}
public class SecondClass
{
private ISomeDependency _dependency;
public SecondClass(SomeDependency.Factory factory)
{
_dependency = factory.Invoke("my value 2");
}
}
}
}

Testing mocked EF context, context and unit of work with RhinoMocks and NUnit

I am having real problems mocking my code to enable me to test my MVC controllers.
My repository implements the following interface
public interface IEntityRepository<T>
{
IQueryable<T> All { get; }
IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties);
void Delete(int id);
T Find(int id);
void InsertOrUpdate(T entity);
void InsertOrUpdateGraph(T entity);
}
Like so
public interface IMonkeyRepository : IEntityRepository<Monkey>
{
}
My EF context implements the following interface
public interface IMonkeyContext
{
IDbSet<Monkey> Monkeys { get; set; }
DbEntityEntry Entry(object entity);
IEnumerable<DbEntityValidationResult> GetValidationErrors();
int SaveChanges();
}
My unit of work interface is defined like so
public interface IUnitOfWork<TContext> : IDisposable
{
TContext Context { get; }
int Save();
}
And implemented
public class MonkeyUnitOfWork : IUnitOfWork<IMonkeyContext>
{
private readonly IMonkeyContext context;
private bool disposed;
public MonkeyUnitOfWork(IMonkeyContext context)
{
this.context = context;
}
public IMonkeyContext Context
{
get
{
return this.context;
}
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
public int Save()
{
var ret = this.context.SaveChanges();
return ret;
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
((DbContext)this.context).Dispose();
}
}
this.disposed = true;
}
}
I have a MonkeyController whos Create action I wish to test. I is defined
if (this.ModelState.IsValid)
{
this.repo.InsertOrUpdate(Mapper.Map<MonkeyModel, Monkey>(monkey));
this.uow.Save();
return this.RedirectToAction(MVC.Monkey.Index());
}
return this.View(monkey);
In my unit test I am using RhinoMocks and have defined the test
[TestFixture]
public class MonkeyControllerTests
{
MockRepository mocks = null;
private IMonkeyRepository monkeyRepository;
private IMonkeyContext context;
private MonkeyUnitOfWork unitOfWork;
private MonkeyController controller;
[SetUp]
public virtual void SetUp()
{
TestHelpers.SetupAutoMap();
this.monkeyRepository = this.Mocks.StrictMultiMock<IMonkeyRepository>(typeof(IEntityRepository<Monkey>));
this.context = this.Mocks.StrictMock<IMonkeyContext>();
this.unitOfWork = new MonkeyUnitOfWork(this.context);
this.controller = new MonkeyController(this.MonkeyRepository, this.unitOfWork);
}
[TearDown]
public virtual void TearDown()
{
if (this.mocks != null)
{
try
{
this.mocks.ReplayAll();
this.mocks.VerifyAll();
}
finally
{
this.mocks = null;
}
}
}
public MockRepository Mocks
{
get
{
if (mocks == null)
mocks = new MockRepository();
return mocks;
}
}
[Test]
public void MonkeyCreateShouldShouldDoSomeStuff()
{
var monkeyModel = ViewModelTestHelpers.CreateSingleMonkey();
var monkey = Mapper.Map<MonkeyModel, Monkey>(monkeyModel);
this.monkeyRepository.Expect(action => action.InsertOrUpdate(monkey));
this.context.Expect(action => action.SaveChanges()).Return(1);
var result = (RedirectToRouteResult)this.controller.Create(monkeyModel);
Assert.AreEqual(MVC.Monnkey.ActionNames.Index, result.RouteValues["action"]);
}
}
When I run my tests I either get the following errror
Previous method 'IMonkeyContext.SaveChanges();' requires a return value or an exception to throw.
Or it complains that the IEntityRepository.InsertOrUpdate expected 1 actual 0
I have tried so many casts, and incantations to get this to work but I am stumped. Does anyone know how to mock these object correctly? Or if I have fundamentaly missed something here?
Well it would seem to be a schoolboy error
RhinoMocks was correct when it said that IEntityRepository.InsertOrUpdate was not being called.
the line of code where I map from view model to model in my test
var monkey = Mapper.Map<MonkeyModel, Monkey>(monkeyModel);
and then use it in the expect
this.monkeyRepository.Expect(action => action.InsertOrUpdate(monkey));
was of course telling Rhino that the function should be called with this exact instance of monkey.
The function is of course called in the following way within the action
this.repo.InsertOrUpdate(Mapper.Map<MonkeyModel, Monkey>(monkey));
Not the same instance.
I have moved to the aaa syntax now and changed the test code to
this.monkeyRepository.Stub(r => r.InsertOrUpdate(Arg<Monkey>.Is.Anything));
and assert
this.monkeyRepository.AssertWasCalled(r => r.InsertOrUpdate(Arg<Monkey>.Is.Anything));
I will now go and hang my head in shame.

Resources