Unity: "new up" one class based on another concrete class?
I might be trying to "mis-use" Unity here, but what I'd like is for Unity to create a new class not based on an interface that the newe'd up class implements, but based on a different class.
This has to do with resolving a concrete DataMapper type based on the name of an domain object being passed into a method call in a DataContext object (in this case, it's a concrete DataContext for Sql Server)
protected override IDataMapper<T> GetDataMapper<T>()
{
if (typeof(T) == typeof(Expert))
{
return (IDataMapper<T>)new ExpertDataMapper();
}
else if (typeof(T) == typeof(Case))
{
return (IDataMapper<T>)new CaseDataMapper();
}
else if (typeof(T) == typeof(CaseFile))
{
return (IDataMapper<T>)new CaseFileDataMapper();
}
etc... etc...
}
You get the point.
in this case, T will be the name of the domain object, NOT the name of the DataMapper that implements the IDataMapper interface... so a call like this:
IDataMapper<T> mapper = (IDataMapper<T>)container.Resolve(t);
fails开发者_StackOverflow中文版.
The GetDataMapper call uses generics, and based on the name of a domain object (let's say "Expert"), I want to instantiate an ExpertDataMapper object, and return that.
What I don't want is this "dumb" factory approach, where it's a huge list of case statements... especially when it comes time to add new domain objects and they're related DataMappers. I'd rather handle that in the config section of my App.config file and NOT have to come in, change code, recompile, and then release to production.
Maybe Unity is the wrong tool for the job?
Thanks! Mike
You can't register IDataMapper<Category>
in configuration file because it is C# syntax but not a generic type's name. Check rules from type names here.
You should use something like (simplifyed Unity 2.0 config):
<unity>
<alias alias="ICategoryMapper"
type="MyNamespace.IDataMapper`1[MyNamespace.Category], MyAssembly" />
<alias alias="CategoryDataMapper"
type="MyNamespace.CategoryDataMapper, MyAssembly" />
<container>
<register type="ICategoryMapper" mapTo="CategoryDataMapper" />
</container>
</unity>
Okay, after poking around a bit more, I got it working like this
Type t = typeof(T);
UnityContainer container = new UnityContainer();
container.RegisterType<IDataMapper<Category>, CategoryDataMapper>();
container.RegisterType<IDataMapper<Expert>, ExpertDataMapper>();
etc... etc...
IDataMapper<T> mapper = (IDataMapper<T>)container.Resolve<IDataMapper<T>>();
that seemed to do it!
but if I continue to use .RegisterType<>, I'm back in the same boat... just instead of a bunch of Case statements, I know have a bunch of .RegisterType<> lines...
So I'm trying to move the RegisterType calls into my App.config file, and I'm running into problems with how to map the Generic interfaces to the concrete mappers...
I have this so far, and it's not working:
<unity>
<containers>
<container>
<types>
<type type="IDataMapper<Category>" mapTo="CategoryDataMapper">
</type>
</types>
</container>
</containers>
</unity>
I've tried the full namespace as well, but no dice. Unity does not like trying to load the type "IDataMapper"...
any ideas?
精彩评论