Register and Resolve Generic Objects - automapper

i have some problems with Register my Interfaces.
I have the following Interfaces:
public interface IMapper<Q, T> { /* Mapper Helper Methods */ }
public interface ISourceObject { /* Properties */ }
public interface ITargetObject { /* Properties */ }
The Implementations are:
public class GenericMapper<Q, T> : IMapper<Q,T> { /* Mapper Helper Methods */ }
public class SourceObject : ISourceObject { /* Properties */ }
public class TargetObject : ITargetObject { /* Properties */ }
In my Autofac Module i want to Register it as following:
builder.RegisterType<GenericMapper<SourceObject, TargetObject>>().As<IMapper<ISourceObject, ITargetObject>>();
And resolve it via:
Container.Resolve<IMapper<ISourceObject, ITargetObject>>();
The Automapper Profile Configuration is:
CreateMap<ISourceObject, ITargetObject>()
// ForMember Mappings
.ForAllMembers(o => o.Condition((src, dest, value) => value != null));
When i start my Unittest, it crashes with the following Stacktrace:
at Autofac.Builder.RegistrationBuilder.CreateRegistration(Guid id, RegistrationData data, IInstanceActivator activator, IEnumerable`1 services, IComponentRegistration target)
at Autofac.Builder.RegistrationBuilder.CreateRegistration[TLimit,TActivatorData,TSingleRegistrationStyle](IRegistrationBuilder`3 builder)
at Autofac.Builder.RegistrationBuilder.RegisterSingleComponent[TLimit,TActivatorData,TSingleRegistrationStyle](IComponentRegistry cr, IRegistrationBuilder`3 builder)
at Autofac.RegistrationExtensions.<>c__DisplayClass3_0`1.<RegisterType>b__0(IComponentRegistry cr)
at Autofac.ContainerBuilder.Build(IComponentRegistry componentRegistry, Boolean excludeDefaultModules)
at Autofac.ContainerBuilder.Build(ContainerBuildOptions options)
System.ArgumentException:
System.ArgumentException: The type 'App.Test.Models.GenericMapper`2[App.Test.Models.SourceObject,App.Test.Models.TargetObject]' is not assignable
to service 'App.Test.Models.IMapper`2[[App.Test.Models.ISourceObject, App.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],
[App.Test.Models.ITargetObject, App.Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'..
What do i wrong here?
When i Register the Implementations, the resolving works without a Problem. But it would be Hardwired to the implementations and that, i dont want. Can i resolve it that way or do i have to use the hard wired Version?

What you have is a problem with your interface definitions. If you pull Autofac entirely out of the mix and just test it manually, you can see the evidence:
[Fact]
public void TypesAreCompatible()
{
var init = new GenericMapper<SourceObject, TargetObject>();
var cast = (IMapper<ISourceObject, ITargetObject>)init;
Assert.Same(init, cast);
}
This will fail on the line that starts with var cast and give the exception:
System.InvalidCastException : Unable to cast object of type 'GenericMapper`2[SourceObject,TargetObject]' to type 'IMapper`2[ISourceObject,ITargetObject]'.
The reason is that your IMapper interface is not covariant. In simpler terms, that means you can't put a more derived type in as Q or T and have it "magically work." It has to be exact.
Update your interface to tell C# that it's OK to use covariant types by putting out in front of the type parameters.
public interface IMapper<out Q, out T> { }
Once you do that, the test I put above will work... and so will the Autofac registration.

Related

Inconsistent accessibility in interface due to internal keyword

By default, a Class, an Interface and struct are
internal in c#. Then why I am not able to access
that same interface wherein I am passing it as a
parameter to a constructor of a class within the same class file?
The solution to mark interface as public is true but then
whats the use of the by default nature of interface which is internal?
// Did not mark as public
interface IGetData
{
string ProvideData(int id);
}
public class EmpClientLogic
{
IGetData _getData;
// Error on this line (if interface is not marked as public)
public EmpClientLogic(IGetData getData)
{
_getData = getData;
}
}

Setting proper Unity Container configuration for resolving interface-class in decorator pattern

Given below are my different class declarations and how I am trying to setup unity container configuration to get a Interface to Concrete class implementation. The code currently throws either an stackoverflow exception or suggests that a interface cannot be constructed.
Please help me fix, either the class structure or the container configuration.
CodesController Class -
public class CodesController : ApiController
{
private readonly IUnitOfWorkAsync unitOfWork;
private readonly ICodeRepository repository;
public CodesController(IUnitOfWorkAsync unitOfWork, ICodeRepository codeRepository)
{
if (unitOfWork == null)
{
throw new ArgumentNullException("unitOfWork");
}
this.unitOfWork = unitOfWork;
this.repository = codeRepository;
}
//Other class level methods here
}
CodeRepository class -
public class CodeRepository : ICodeRepository
{
private readonly ICodeRepository codeRepository;
public CodeRepository(ICodeRepository repository)
{
this.codeRepository = repository;
}
public virtual async Task<IEnumerable<Code>> GetCodeAsync(string codeKey)
{ //Some implementation here}
}
ICodeRepository Interface -
public interface ICodeRepository : IRepositoryAsync<Code>
{
Task<IEnumerable<Code>> GetCodeAsync(string codeKey);
}
IRepositoryAsync Interface -
public interface IRepositoryAsync<TEntity> : IRepository<TEntity> where TEntity : class, IPersistenceHint
{
Task<bool> DeleteAsync(params object[] keyValues);
Task<bool> DeleteAsync(CancellationToken cancellationToken, params object[] keyValues);
Task<TEntity> FindAsync(params object[] keyValues);
Task<TEntity> FindAsync(CancellationToken cancellationToken, params object[] keyValues);
}
Unity Container Configuration-
container.RegisterType<IUnitOfWorkAsync, UnitOfWork>(
"test",
new TransientLifetimeManager(),
new InjectionConstructor(container.Resolve<IDataContextAsync>("test")));
container.RegisterType<ICodeRepository, CodeRepository>();
container.RegisterType<CodesController, CodesController>();
With this given configuration and class structure, based on my experimentation with container config, I get following exception -
JSON
exceptionMessage=An error occurred when trying to create a controller of type 'CodesController'. Make sure that the controller has a parameterless public constructor.
exceptionType=System.InvalidOperationException
innerException
exceptionMessage=Type '<Namespace>.Api.Controllers.CodesController' does not have a default constructor
stackTrace= at System.Linq.Expressions.Expression.New(Type type)
at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
Please suggest, if anything is wrong here, so that I can fix the same. Already struggling many days on this.
You're injecting ICodeRepository to CodeRepository, which probably causes to stackoverflow exception, since it will keep generating ICodeRepositories. It will generate a recursive call. Somewhat like this one:
public class BaseFoo
{
public BaseFoo(BaseFoo foo){ }
}
public class Foo : BaseFoo
{
public Foo() : base(new Foo()) { }
}
And regarding the "does not have a default constructor"-exception, have you registered a DependencyResolver for Web API? See one of these questions for more detailed information how to do it:
Using Unity with Web Api 2 gives error does not have a default constructor
Unity.WebApi | Make sure that the controller has a parameterless public constructor
ASP.Net MVC 4 Web API controller dosn't work with Unity.WebApi
As a side note, you shouldn't have to register the CodesController in your unity registration.

c# generics error: The constraints for type parameter 'T' of method ...?

Getting the following error:
Error 1 The constraints for type parameter 'T' of method
'genericstuff.Models.MyClass.GetCount<T>(string)' must match the constraints for type
parameter 'T' of interface method 'genericstuff.IMyClass.GetCount<T>(string)'. Consider
using an explicit interface implementation instead.
Class:
public class MyClass : IMyClass
{
public int GetCount<T>(string filter)
where T : class
{
NorthwindEntities db = new NorthwindEntities();
return db.CreateObjectSet<T>().Where(filter).Count();
}
}
Interface:
public interface IMyClass
{
int GetCount<T>(string filter);
}
You are restricting your T generic parameter to class in your implementation. You don't have this constraint on your interface.
You need to remove it from your class or add it to your interface to let the code compile:
Since you are calling the method CreateObjectSet<T>(), which requires the class constraint, you need to add it to your interface.
public interface IMyClass
{
int GetCount<T>(string filter) where T : class;
}
You either need to apply the constraint to the interface method as well or remove it from the implementation.
You are changing the interface contract by changing the constraint on the implementation - this isn't allowed.
public interface IMyClass
{
int GetCount<T>(string filter) where T : class;
}
You need to constrain your interface, too.
public interface IMyClass
{
int GetCount<T>(string filter) where T : class;
}

Register component based on parameter name on requestor in windsor

I have this interface for using AutoMapper:
public interface IMapper
{
object Map(object source, Type sourceType, Type destinationType);
}
Then for each type of data, I have a different mapper class , for example:
public class UserMapper : IMapper
{
static UserMapper()
{
Mapper.CreateMap<User, UserViewModel>();
Mapper.CreateMap<UserViewModel, User>();
}
public object Map(object source, Type sourceType, Type destinationType)
{
return Mapper.Map(source, sourceType, destinationType);
}
}
Then I have IMapper as one of the parametter in my controller class like this:
public UsersController(IUsersRepository repo, IMapper userMapper)
{....}
I am using Windsor as the IOC for my application and the problem is that I want to register the components, so that when running in UsersController , it use the UserMapper class and if running on ProductsController it will use my ProductMapper class.
My registration code looks something along the line of this:
container.Register(
Component.For<IMapper>()
.ImplementedBy<UsersMapper>()
.Named("usersMapper"),
Component.For<IMapper>()
.ImplementedBy<ProductsMapper>()
.Named("productsMapper"),
Component.For<ProductController>()
.ServiceOverrides(ServiceOverride.ForKey("usersMapper").Eq("productsMapper"))
)
I have done my homework on google and stackoverflow, and i know that I need to use ServicesOverride but I am still stuck on this, could anyone give me a hand please?
Thanks
While svick's solution looks correct to me (I haven't attempted to compile it, though), this scenario is an excellent case for convention-based configuration.
Let's introduce this convention: Each consumer of IMapper will signal the intended role of the mapper by its name. By default, that name will be matched with a type of the same name - only with different casing.
So, constructor parameters could be mapped like this:
userMapper -> UserMapper
productMapper -> ProductMapper
In Castle Windsor, such a configuration might look like this:
container.Register(Classes
.FromThisAssembly()
.Pick()
.WithServiceAllInterfaces()
.WithServiceSelf());
container.Kernel.Resolver.AddSubResolver(
new MapperConvention(container.Kernel));
And the Sub Resolver (where the magic really happens) looks like this:
public class MapperConvention : ISubDependencyResolver
{
private readonly IKernel kernel;
public MapperConvention(IKernel kernel)
{
this.kernel = kernel;
}
public bool CanResolve(CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
return typeof(IMapper).IsAssignableFrom(dependency.TargetType);
}
public object Resolve(CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
var representativeMapperType = typeof(UserMapper);
var concreteMapperType = representativeMapperType.Assembly
.GetExportedTypes()
.Where(t =>
t.Name.Equals(dependency.DependencyKey,
StringComparison.OrdinalIgnoreCase))
.Single();
return this.kernel.Resolve(concreteMapperType);
}
}
This registration works for me:
container.Register(
Component.For<IMapper>()
.ImplementedBy<UserMapper>()
.Named("userMapper"),
Component.For<IMapper>()
.ImplementedBy<ProductMapper>()
.Named("productMapper"),
Component.For<UsersController>()
.ServiceOverrides(ServiceOverride.ForKey<IMapper>().Eq("userMapper")),
Component.For<ProductsController>()
.ServiceOverrides(ServiceOverride.ForKey<IMapper>().Eq("productMapper"))
);

looking for a proper way to implement my generic factory

I'm struggling with implementing a factory object. Here's the context :
I've in a project a custom store. In order to read/write records, I've written this code in a POCO model/separated repository:
public class Id { /* skip for clarity*/} // My custom ID representation
public interface IId
{
Id Id { get; set; }
}
public interface IGenericRepository<T> where T : IId
{
T Get(Id objectID);
void Save(T #object);
}
public interface IContext
{
TRepository GetRepository<T, TRepository>()
where TRepository : IGenericRepository<T>
where T:IId;
IGenericRepository<T> GetRepository<T>()
where T:IId;
}
My IContext interface defines two kind of repositories.
The former is for standard objects with only get/save methods, the later allows me to define specifics methods for specific kind of objects. For example :
public interface IWebServiceLogRepository : IGenericRepository<WebServiceLog>
{
ICollection<WebServiceLog> GetOpenLogs(Id objectID);
}
And it the consuming code I can do one of this :
MyContext.GetRepository<Customer>().Get(myID); --> standard get
MyContext.GetRepository<WebServiceLog, IWebServiceLogRepository>().GetOpenLogs(myID); --> specific operation
Because most of objects repository are limited to get and save operations, I've written a generic repository :
public class BaseRepository<T> : IGenericRepository<T>
where T : IId, new()
{
public virtual T Get(Id objectID){ /* provider specific */ }
public void Save(T #object) { /* provider specific */ }
}
and, for custom ones, I simply inherits the base repository :
internal class WebServiceLogRepository: BaseRepository<WebServiceLog>, IWebServiceLogRepository
{
public ICollection<WebServiceLog> GetByOpenLogsByRecordID(Id objectID)
{
/* provider specific */
}
}
Everything above is ok (at least I think it's ok). I'm now struggling to implement the MyContext class. I'm using MEF in my project for other purposes. But because MEF doesn't support (yet) generic exports, I did not find a way to reach my goal.
My context class is looking like by now :
[Export(typeof(IContext))]
public class UpdateContext : IContext
{
private System.Collections.Generic.Dictionary<Type, object> m_Implementations;
public UpdateContext()
{
m_Implementations = new System.Collections.Generic.Dictionary<Type, object>();
}
public TRepository GetRepository<T, TRepository>()
where T : IId
where TRepository : IGenericRepository<T>
{
var tType = typeof(T);
if (!m_Implementations.ContainsKey(tType))
{
/* this code is neither working nor elegant for me */
var resultType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(
(a) => a.GetTypes()
).Where((t)=>t.GetInterfaces().Contains(typeof(TRepository))).Single();
var result = (TRepository)resultType.InvokeMember("new", System.Reflection.BindingFlags.CreateInstance, null, null, new object[] { this });
m_Implementations.Add(tType, result);
}
return (TRepository)m_Implementations[tType];
}
public IGenericRepository<T> GetRepository<T>() where T : IId
{
return GetRepository<T, IGenericRepository<T>>();
}
}
I'd appreciate a bit of help to unpuzzle my mind with this quite common scenario
Not sure if I've understood you correctly, but I think you're perhaps over complicating things. To begin with, make sure you've designed your code independent of any factory or Dependency Injection framework or composition framework.
For starters lets look at what you want your calling code to look like, this is what you said:
MyContext.GetRepository<Customer>().Get(myID); --> standard get
MyContext.GetRepository<WebServiceLog, IWebServiceLogRepository>().GetOpenLogs(myID);
You don't have to agree with my naming choices below, but it indicates what I undertand from your code, you can tell me if I'm wrong. Now, I feel like the calling would be simpler like this:
RepositoryFactory.New<IRepository<Customer>>().Get(myId);
RepositoryFactory.New<IWebServiceLogRepository>().GetOpenLogs(myId);
Line 1:
Because the type here is IRepository it's clear what the return type is, and what the T type is for the base IRepository.
Line 2:
The return type here from the factory is IWebServiceLogRepository. Here you don'y need to specify the entity type, your interface logically already implements IRepository. There's no need to specify this again.
So your interface for these would look like this:
public interface IRepository<T>
{
T Get(object Id);
T Save(T object);
}
public interface IWebServiceLogRepository: IRepository<WebServiceLog>
{
List<WebServiceLog> GetOpenLogs(object Id);
}
Now I think the implementations and factory code for this would be simpler as the factory only has to know about a single type. On line 1 the type is IRepository, and in line 2, IWebServiceLogRepository.
Try that, and try rewriting your code to simply find classes that implement those types and instantiating them.
Lastly, in terms of MEF, you could carry on using that, but Castle Windsor would really make things much simpler for you, as it lets you concentrate on your architecture and code design, and its very very simple to use. You only ever reference Castle in your app startup code. The rest of your code is simply designed using the Dependency Injection pattern, which is framework agnostic.
If some of this isn't clear, let me know if you'd like me to update this answer with the implementation code of your repositories too.
UPDATE
and here's the code which resolves the implementations. You were making it a bit harder for yourself by not using the Activator class.
If you use Activator and use only one Generic parameter as I've done in the method below, you should be ok. Note the code's a bit rough but you get the idea:
public static T GetThing<T>()
{
List<Type> assemblyTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes()).ToList();
Type interfaceType = typeof(T);
if(interfaceType.IsGenericType)
{
var gens = interfaceType.GetGenericArguments();
List<Type> narrowed = assemblyTypes.Where(p => p.IsGenericType && !p.IsInterface).ToList();
var implementations = new List<Type>();
narrowed.ForEach(t=>
{
try
{
var imp = t.MakeGenericType(gens);
if(interfaceType.IsAssignableFrom(imp))
{
implementations.Add(imp);
}
}catch
{
}
});
return (T)Activator.CreateInstance(implementations.First());
}
else
{
List<Type> implementations = assemblyTypes.Where(p => interfaceType.IsAssignableFrom(p) && !p.IsInterface).ToList();
return (T)Activator.CreateInstance(implementations.First());
}
}

Resources