MEF Constructor Injection - c#

I'm trying to figure out MEF's Constructor Injection attribute. I have no idea how I tell it to load the constructor's parameters.
This is the property I'm trying to load
[ImportMany(typeof(BUsers))]
public IEnumerable<BUsers> LoadBUsers { get; set; }
Here is the code I'm using to import the assemblies.
try
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()));
catalog.Catalogs.Add(new DirectoryCatalog("DI"));
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
}
Here is the class I'm trying to load
[Serializable]
[Export(typeof(BUsers))]
public class EditProfile : BUsers
{
[ImportingConstructor]
public EditProfile(string Method, string Version)
{
Version = "2";
Action = "Edit";
TypeName = "EditProfile";
}

When you use the ImportingConstructor attribute, the parameters to the constructor become imports. By default, what you are importing (the contract name) is based on the type of the parameter or property that your are importing into. So in this case the contract type for both your imports is string, and there's no real difference between the first and second parameter.
It looks like you are trying to use imports to supply configuration values, which isn't necessarily what it was designed for. To get it to do what you want, you should override the contract name for each of the parameters, like this:
[ImportingConstructor]
public EditProfile([Import("Method")] string Method, [Import("Version")] string Version)
{ }
Then you need exports for Method and Version in your container. One way to do this is just to add them directly:
var container = new CompositionContainer(catalog);
container.ComposeExportedValue("Method", "MethodValue");
container.ComposeExportedValue("Version", "2.0");
container.ComposeParts(this);
(Note that ComposeExportedValue is actually an extension method defined on the static AttributedModelServices class.)
If you want to read these values from a configuration file of some sort, you could create your own export provider which reads the configuration and provides the values in it as exports to the container.
An alternative way to handle this would be to just import an interface that provides access to the configuration values by name, and get the values you need from the body of the constructor.

I like Daniel's solution; however, only one thing I see is the tight coupling of parameter names between the actor (who creates CompopositionContrainer()) and Export part with [ImportingConstructor] for customized CTOR. For example, "Method" has two be matched in both places. It makes hard to maintain the Export part if the actor and Export part are in difference projects.
If it is possible, I would add the second CTOR to the Export part class. For example:
[Export(typeof(BUsers))]
public class EditProfile : BUsers
{
[ImportingConstructor]
public EditProfile(EditProfileParameters ctorPars)
: this(ctorPars.Method, ctorPars.Version) {}
public EditProfile(string Method, string Version)
{
Version = "2";
Action = "Edit";
TypeName = "EditProfile";
}
The class of EditProfileParameters should be straightforward: two properties of Method and Version:
[Export]
public class EditProfileParameters{
public string Method { get; set; }
public string Version { get; set; }
}
The key point is to add Export attribute to the class. Then MEF should be able to map this class to the parameter of EditProfile's CTOR.
Here is example to add the Export part to container:
var container = new CompositionContainer(catalog);
var instance1 = new EditProfileParameters();
// set property values from config or other resources
container.ComposeExportedValue(instance1);
container.ComposeParts(this);

Although late to the game, here's another approach that leverages a lesser-known feature of MEF: Property Exports
public class ObjectMother
{
[Export]
public static EditProfile DefaultEditProfile
{
get
{
var method = ConfigurationManager.AppSettings["method"];
var version = ConfigurationManager.AppSettings["version"];
return new EditProfile(method,version);
}
}
}
No usages are required for ObjectMother for this to work, and no attributes are required on EditProfile.

Related

How do I handle a configuration class that are loaded at runtime with dependency injection?

I'm currently trying to work with dependency injection and so far I love. But it's one thing I can't really get my head around and where my current solution just seems wrong.
I'm working with WPF, MVVM and many of the classes I inject need an instance of a project configuration class that isn't initialized until the user create or open a new project in the application.
So my current solution is to have a "ConfigurationHandler" with load/save method and a property that hold an instance of the configuration class after it's loaded. I inject ConfigurationHandler to the others classes and then they can access the configuration after it's loaded. But it seems weird to let classes that never should save/load configuration handle the whole "ConfigurationHandler" and 100% they would just use it to access the configuration instance likt this:
var configuration = configurationHandler.Configuration;
Another problem is that if they try to access the configuration before it's loaded they will get exception (should not really happen as you can't do anything before a project is created/loaded, but still).
But the only other solution I can think of is to use "intialize" methods after a project is created/open but that seems just as bad.
So how do you usually handle cases like this?
Edit: Should add that this configuration class handle information like project path, project name, etc so have nothing to do with the dependency injection itself.
If your configuration is static (read: It's only read during startup of your application, such as from project.json or Web.Config), you can also set it during app startup/the composition root.
The new ASP.NET 5 uses it heavily and it works very well. Basically you will have an IConfiguration<T> interface and a POCO class, which you set up during the app startup and can resolve/inject it into your services.
public interface IConfiguration<T> where T : class
{
T Configuration { get; }
}
And it's default implementation
public interface DefaultConfiguration<T> where T : class
{
private readonly T configuration;
public T Configuration {
return configuration;
}
public DefaultConfiguration<T>(T config)
{
this.configuration = this.configuration;
}
}
And your POCO class
public class AppConfiguration
{
public string OneOption { get; set; }
public string OtherOption { get; set; }
}
In your composition root, you would then register it, like
// read Web.Config
Configuration rootWebConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(null);
container.AddSingleton<IConfiguration<AppConfiguration>>(new DefaultConfiguration<AppConfiguration>(
new AppConfiguration
{
OneOption = rootWebConfig.AppSettings.Settings["oneSetting"],
OtherOption = rootWebConfig.AppSettings.Settings["otherSetting"],
})
);
And finally, all you have to declare in your services is
public class MyService : IMyService
{
public MyService(IUserRepository, IConfiguration<AppConfiguration> appConfig)
{
...
if(appConfig.OneOption=="someValue") {
// do something
};
}
}
Finally you can make this a bit easier to configure, if you write an extension method like
public static class MyContainerExtension
{
public static void Configure<T>(this IMyContainer container, Action<T> config) where T : class, new()
{
var t = new T();
config(t);
container.AddSingelton<IConfiguration<T>>(t);
}
}
Then all you need to do is
container.Configure<AppConfiguration>(
config =>
{
config.OneOption = rootWebConfig.AppSettings.Settings["oneSetting"],
config.OtherOption = rootWebConfig.AppSettings.Settings["otherSetting"],
})
);
to set it up
Instead of Constructor Injection, consider using an Ambient Context approach.
The last type of DI we’ll discuss is making dependencies available
through a static accessor. It is also called injection through the
ambient context. It is used when implementing cross-cutting concerns.
This is a good option if the classes that need access to your configuration are of different types in different layers or libraries - i.e. is a true cross-cutting concern.
(Quote source)
Example, based on the classic Time Provider one from [Dependency Injection in .NET][2]
abstract class CustomConfiguration
{
//current dependency stored in static field
private static CustomConfiguration current;
//static property which gives access to dependency
public static CustomConfiguration Current
{
get
{
if (current == null)
{
//Ambient Context can't return null, so we assign a Local Default
current = new DefaultCustomConfiguration();
}
return current;
}
set
{
//allows to set different implementation of abstraction than Local Default
current = (value == null) ? new DefaultCustomConfiguration() : value;
}
}
//service which should be override by subclass
public virtual string SomeSetting { get; }
}
//Local Default
class DefaultCustomConfiguration : CustomConfiguration
{
public override string SomeSetting
{
get { return "setting"; }
}
}
Usage
CustomConfiguration.Current.SomeSetting;
There are other DI Patterns that could be used, but require changes to the class that need it. If Configuration is a cross cutting concern Ambient Context could be the best fit.
Constructor Injection Example
public SomeClass(IConfiguration config)
{
}
Property Injection
public SomeClass()
{
IConfiguration configuration { get; set; }
}
Method Injection
public SomeClass()
{
public void DoSomethingNeedingConfiguation(IConfiguration config)
{
}
}
There is also Service Locator, but Service Locator is (IMO) an anti-pattern.

More than one export was found that matches the constraint for non ICollection<T>

I looked at several other other posts that talk about using:
[ImportMany]
IEnumerable<IPlugin> plugins;
but in my case it is not a collection.
Please see below for my code and error message:
[Export(typeof(ITransactionActionMasterDao))]
public class TransactionActionMasterDao : BaseDao, ITransactionActionMasterDao
public abstract class BaseTransactionGenerator : ITransactionGenerator
{
[Import(typeof(ITransactionActionMasterDao))]
private ITransactionActionMasterDao transactionActionMasterDao;
public BaseTransactionGenerator()
{
//Grab all the assemblies in the current folder
AggregateCatalog catalog = new AggregateCatalog(new AssemblyCatalog( typeof(TransactionActionMasterDao).Assembly) );
CompositionContainer container = new CompositionContainer(catalog);
// This will set the fields (aka execute the [Import])
**//below line getting error**
container.ComposeParts(this);
}
}
public class ManualTransactionGenerator : BaseTransactionGenerator
{
public ManualTransactionGenerator():base()
{
}
}
ManualTransactionGenerator and BaseTransactionGenerator are both in one same C# class library project.
TransactionGeneratorsIntegrationTest is present in another UnitTest project
public class TransactionGeneratorsIntegrationTest
{
[TestMethod]
public void IT_GenerateManualTransactions()
{
ManualTransactionGenerator generator = new ManualTransactionGenerator()
}
}
Error Message:
The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.
1) More than one export was found that matches the constraint:
ContractName HL.DataAccess.Adjustment.Contracts.DataAccessObjects.ITransactionActionMasterDao
RequiredTypeIdentity HL.DataAccess.Adjustment.Contracts.DataAccessObjects.ITransactionActionMasterDao
UPDATE:
We changed our design and new code looks like this
[Export(typeof(ITransactionActionMasterDao))]
public class TransactionActionMasterDao : BaseDao, ITransactionActionMasterDao
[Export(typeof(ITransactionActionMasterDao))]
public class CustomerTransactionActionMasterDao : BaseDao, ITransactionActionMasterDao
public abstract class BaseTransactionGenerator : ITransactionGenerator
{
[Import(typeof(ITransactionActionMasterDao))]
private ITransactionActionMasterDao transactionActionMasterDao;
public BaseTransactionGenerator()
{
**//Below lines will throw error**
AggregateCatalog catalog = new AggregateCatalog(new AssemblyCatalog( typeof(TransactionActionMasterDao).Assembly),
new AssemblyCatalog( typeof(CustomerTransactionActionMasterDao ).Assembly) );
**//This is correct. We need to add ONLY one. Not both**
AggregateCatalog catalog = new AggregateCatalog(new AssemblyCatalog( typeof(TransactionActionMasterDao).Assembly);
CompositionContainer container = new CompositionContainer(catalog);
// This will set the fields (aka execute the [Import])
**//below line getting error**
container.ComposeParts(this);
}
}
This solved our issue.
You may be encountering a problem with side-by-side loading of multiple versions of the assembly containing the [Export] attribute. To test this theory, try the following:
Change the [Import] to an [ImportMany].
If (when) you observe more than one item in the list, examine each instance to determine the location of the assembly it was loaded from.
transactionActionMasterDao[i].GetType().Assembly.Location
If this is the case, you may need to use assembly binding redirection to ensure only one copy of the assembly containing the export is loaded.

DI with Unity when multiple instances of the same type is needed

I need help with this. I'm using Unity as my container and I want to inject two different instances of the same type into my constructor.
class Example
{
Example(IQueue receiveQueue, IQueue sendQueue) {}
}
....and IQueue is implemented in my MessageQueue class....
class MessageQueue : IQueue
{
MessageQueue(string path) {}
}
How can I inject two different instances of MessageQueue into my Example class? Each of the MessageQueue instances to be created with different path.
There are many ways to achieve the results you want (as evidenced by the multiple answers). Here is another way using named registrations (without attributes):
IUnityContainer container = new UnityContainer();
container.RegisterType<IQueue, MessageQueue>("ReceiveQueue",
new InjectionConstructor("receivePath"));
container.RegisterType<IQueue, MessageQueue>("SendQueue",
new InjectionConstructor("sendPath"));
container.RegisterType<Example>(
new InjectionConstructor(
new ResolvedParameter<IQueue>("ReceiveQueue"),
new ResolvedParameter<IQueue>("SendQueue")));
Example example = container.Resolve<Example>();
The downside of this approach is that if the Example constructor is changed then the registration code must also be modified to match. Also, the error would be a runtime error and not a more preferable compile time error.
You could combine the above with an InjectionFactory to invoke the constructor manually to give compile time checking:
IUnityContainer container = new UnityContainer();
container.RegisterType<IQueue, MessageQueue>("ReceiveQueue",
new InjectionConstructor("receivePath"));
container.RegisterType<IQueue, MessageQueue>("SendQueue",
new InjectionConstructor("sendPath"));
container.RegisterType<Example>(new InjectionFactory(c =>
new Example(c.Resolve<IQueue>("ReceiveQueue"),
c.Resolve<IQueue>("SendQueue"))));
Example example = container.Resolve<Example>();
If you are using a composition root then the use of the magic strings ("ReceiveQueue" and "SendQueue") would be limited to the one registration location.
Not everything has to be automatically wired by the container. You can register the Example class like this:
container.Register<Example>(new InjectionFactory(c =>
{
var receive = new MessageQueue("receivePath");
var send = new MessageQueue("sendPath");
return new Example(receive, send);
});
You could register the two instances with names:
myContainer.RegisterInstance<IQueue>("ReceiveQueue", myReceiveMessageQueue);
myContainer.RegisterInstance<IQueue>("SendQueue", mySendMessageQueue);
and then you should be able to resolve by name, but it requires using the Dependency attribute:
class Example
{
Example([Dependency("ReceiveQueue")] IQueue receiveQueue,
[Dependency("SendQueue")] IQueue sendQueue) {
}
}
or inject the unity container and then resolve the instances within the constructor:
class Example
{
Example(IUnityContainter container)
{
_receiveQueue = container.Resolve<IQueue>("ReceiveQueue");
_sendQueue = container.Resolve<IQueue>("SendQueue");
}
}
Well, don't
You should use the factory pattern in this case.
class Example
{
Example(IQueueFactory factory)
{
_sendQueue = factory.Create("MySend");
_receiveQueue = factory.Create("MyReceive");
}
}
It makes the intention a lot more clear and you can internally in the Example class handle if the queues are not found or incorrectly configured.
5 years later, but I was looking for this answer too.
I worked through it with my own code and then decided to create working code using (slightly altered) classes the OP provided.
This is an entire working example that you can copy into LINQPad (programmer's playground) and run.
Using Statement / Unity Libary
You'll need to add a reference to Microsoft.Practices.Unity.dll
You'll also need to add a using statement of :
Microsoft.Practices.Unity
In LinqPad you press F4 to add the reference and the using statement (namespace import).
void Main()
{
// Create your unity container (one-time creation)
UnityContainer uc = new UnityContainer();
// Create simple list to hold your target objects
// (makes the sample easy to follow)
List<MessageQueue> allMQs = new List<MessageQueue>();
// I'm adding TransientLifetimeManager() in order to
// explicitly ask for new object creation each time
// uc.Resolve<MessageQueue>() is called
uc.RegisterType<IQueue, MessageQueue>(new TransientLifetimeManager());
// ### override the parameters by matching the parameter name (inPath)
var item = uc.Resolve<MessageQueue>(new ParameterOverride("inPath", "extra.txt").OnType<MessageQueue>());
allMQs.Add(item);
item = uc.Resolve<MessageQueue>(new ParameterOverride("inPath", "super.txt").OnType<MessageQueue>());
allMQs.Add(item);
foreach (MessageQueue mq in allMQs){
Console.WriteLine($"mq.Path : {mq.Path}");
}
Console.WriteLine("######################\n");
uc.RegisterType<Example>(new InjectionConstructor((allMQs[0] as IQueue),(allMQs[1] as IQueue)));
// #### Create a new Example from the UnityContainer
var example1 = uc.Resolve<Example>();
// ##### Notice that the Example object uses the default values of super.txt & extra.txt
Console.WriteLine("#### example1 obj. uses default values ###########");
Console.WriteLine($"example1.receiver.Path : {example1.receiver.Path}");
Console.WriteLine($"example1.sender.Path : {example1.sender.Path}");
// ##################################################
// Override the parameters that he Example class uses.
// ### override the parameters by matching the parameter
// names (receiveQueue, sendQueue) found in the target
// class constructor (Example class)
var example2 = uc.Resolve<Example>(
new ParameterOverrides {
{"receiveQueue", new MessageQueue("newReceiveFile")},
{ "sendQueue", new MessageQueue("newSendFile")}
}.OnType<Example>());
Console.WriteLine("######################\n");
Console.WriteLine("#### example1 obj. uses ParameterOverride values ###########");
Console.WriteLine($"example2.sender.Path : {example2.sender.Path}");
Console.WriteLine($"example2.receiver.Path : {example2.receiver.Path}");
}
class Example
{
public MessageQueue receiver {get;set;}
public MessageQueue sender {get;set;}
public Example(IQueue receiveQueue, IQueue sendQueue) {
this.receiver = receiveQueue as MessageQueue;
this.sender = sendQueue as MessageQueue;
}
}
public class MessageQueue : IQueue
{
public string Path {get;set;}
public MessageQueue(string inPath) {
Path = inPath;}
}
interface IQueue{
}
Output For Examination
If you run the script above you'll see sample output which will look like the following:
mq.Path : extra.txt
mq.Path : super.txt
######################
#### example1 obj. uses default values ###########
example1.receiver.Path : extra.txt
example1.sender.Path : super.txt
######################
#### example1 obj. uses ParameterOverride values ###########
example2.sender.Path : newSendFile
example2.receiver.Path : newReceiveFile
I think this has been asked before on Stackoverflow.
You need to use ParameterOverride:
ParameterOverride enables you to pass in values for constructor parameters to override a parameter passed to a given named constructor. Only the parameter value is overridden, not the constructor.
Link to MSDN Article
Link to Stackoverflow Article
var exampleInstance = new Example();
var queue1 = unityContainer.Resolve<IQueue>(new ParameterOverrides<MessageQueue> { { "path", "yourPath" }});
var queue2 = unityContainer.Resolve<IQueue>(new ParameterOverrides<MessageQueue> { { "path", "yourPath2Queue2" }});
exampleInstance.Example(queue1,queue2);

How to inject N MEF exports into 1 Unity composite service using MefContrib or other technique?

Let's say I have 5 separate assemblies with the following (assume the class name is different in each):
[Export(typeof(IService))]
public class Service: IService
{
// ...
}
And I have a class that will be a composite of these in my main assembly
public class CompositeService : IService
{
public CompositeService(IEnumerable<IService> services)
{
// ...
}
}
What I would like to do is have the Unity container resolve the CompositeService for the IService and have the MefContrib extension for Unity go and find the 5 other exports and inject them into CompositeService's constructor.
The problem is that you can't have N instances for a nameless unityContainer.RegisterType<IService> nor can you for named instances if they all have the same name.
I think I'm missing something simple in the combination of the 2 technologies (Unity + MEF) via the third (MefContrib) but can't seem to pick up on what it is.
Is this possible or is there a workaround? Eventually, I'm going for full bi-directional dependency injection and dynamic component discovery.
I think what is likely the best approach is to flip this around. Instead of trying to register your components via Unity, you actually leave the discovery of these parts to MEF. MEFContrib includes an Unity integration mechanism that allows your MEF composed parts to be injected into Unity components. This was original detailed at Piotr WŁodek's blog, whereby he also gives you a sample. Essentialy, the way it works is you can use a series of extension methods on your UnityContainer to register your catalogs. Internally, it will create the appropriate extension and wire up your container.
Here is a quick and dirty example, we'll create some interfaces:
public interface IUnityComponent
{
IEnumerable<IMefComponent> MefComponents { get; }
}
public interface IMefComponent
{
string Name { get; }
}
And then some sample parts which we'll export (via MEF):
[Export(typeof(IMefComponent))]
public class MefComponent1 : IMefComponent
{
public string Name { get { return "MEF Component 1"; } }
}
[Export(typeof(IMefComponent))]
public class MefComponent2 : IMefComponent
{
public string Name { get { return "MEF Component 2"; } }
}
Now, we'll create another part (this will be created via Unity):
public class UnityComponent : IUnityComponent
{
public UnityComponent(IEnumerable<IMefComponent> mefComponents)
{
// mefComponents should be provided from your MEF container.
MefComponents = mefComponents;
}
public IEnumerable<IMefComponent> MefComponents { get; private set; }
}
To wire it all up, we simply need to use the RegisterCatalog extension method on your UnityContainer (import MefContrib.Integration.Unity after you've added a reference to MEFContrib):
var container = new UnityContainer();
// Register the catalog - this handles MEF integration.
container.RegisterCatalog(new DirectoryCatalog("."));
// Register our Unity components.
container.RegisterType<IUnityComponent, UnityComponent>(new ContainerControlledLifetimeManager());
Now you should be able to grab the instance and enumerate the MEF-provided parts:
// Grab an instance of our component.
var instance = container.Resolve<IUnityComponent>();
foreach (var mefComponent in instance.MefComponents)
{
Console.WriteLine(mefComponent.Name);
}
note: 100% untested.
Just tried the same solution from Matthew here and it is working ok, Unity is picking up the exports from MEF and injecting them into the constructor (which accepts an IEnumerable<>).
Don't know if it can help you, but including both MefContrib and MefContrib.Integration.Unity can help: for a while I only had the latter included and encountered similar errors.
As a side note, keep in mind that all the registrations in Unity (coming from MEF exports) will be "nameless" so if you try ResolveAll<> you will get an empty collection and if you try Resolve<> you will get an exception if there is more than 1 implementation registered.

Microsoft Unity 2, how to register the following?

Right now we have a dll file that contains all the database calls and i can't change it. However i need to call i from my Mvc 3 project. The process to call it is simple, i use the following:
ManageProvider.GetProxy<T>(ident);
T is an interface that i want to get the class back from (its like an IoC of its own) and ident is the user identification class. So by calling
var classReturned = ManageProvider.GetProxy<ICommunity>(new UserIden{ Email = "test#test.com" });
I would get a class back with all the community functions.
Now i want to implement Unity in my Mvc 3 project. The question is, can i somehow add these calls to the dll file through unity?
I want to resolve the call by using:
var classReturned = myContainer.Resolve<ICommunity>(new UserIden{ Email = "test#test.com" });
How can i register this in Unity (or is it even possible) ?
Update:
1) Is it better to call the methods with the email/user ident instead of defining a Dependency property? (ex below)
2) There is a bout 20 or so interfaces in the dll file right now. Should i add them all to the same reposatory? (ex below)
public class ProxyWrapper : IDllRepository
{
[Dependency]
public UserIdent UserIdent { get; set; }
public ICommunity GetCommunity()
{
return ManageProvider.GetProxy<ICommunity>(UserIdent);
}
public IDesktop GetDesktop()
{
return ManageProvider.GetProxy<IDesktop>(UserIdent);
}
}
public interface IDllRepository
{
ICommunity GetCommunity();
IDesktop GetDesktop();
}
Whats the best way and how would i call it from my code?
Does the [Dependency] attribute also fall into the Service Locator anti pattern?
Update 23.05.11
1) Yes, something like that. They contain all the logic that is provided to all the projects that includes the dll file.
Regarding the ManagerProvider. It accepts an interface and returns the class that is mapped to this interface. So for the community, the interface looks like this (removed a lot of calls to keep it short, there is also posts, comments, community create/update etc):
List<CommunityThread> GetThreads(int pStartRowIndex, int pMaximumRows, string pOrderBy, string pSearchExpression);
Guid? CreateThread(string pTitle, string pDescription, string pPostContent);
bool DeleteThread(Guid pThreadId);
List<CommunityThread> GetCommunityUserThreads(Guid pCommunityUserId);
2) What i can't update is how the ManageProvider.GetProxy works. The GetProxy is a class in the dll file that is hardcoded. Here is the part for the community. The class does the same for all the other interfaces as well, if typeof(interface) ... return class.
private static IManageProxy GetProxyForInterface<T>(UserIdent pIdent)
{
....
if (typeof(T).Equals(typeof(ICommunity)))
return new PCommunity();
....
}
3) Once registered using this new wrapper class, i can call it through the following code (MvcUnityContainer is a static class that only has a property called Container):
var c = MvcUnityContainer.Container.Resolve<IBackendRepository>(new PropertyOverride("UserIdent",
new UserIdent()));
Global.asax
IUnityContainer container = InitContainer();
MvcUnityContainer.Container = container;
DependencyResolver.SetResolver(new UnityMvcResolver(container));
The question is, do i need the static class MvcUnityContainer? Is it possible to configure the DependecyResolver to do that for me? Something like (problem is that it doesn't accept the override parameter):
var c = DependencyResolver.Current.GetService<IBackendRepository>(new PropertyOverride("UserIdent", new UserIdent()));
I think you need to hide the creation behind another abstraction, for instance:
public interface ICommunityRepository
{
ICommunity GetByEmailAddress(string address);
}
public class ManageProviderCommunityRepository
: ICommunityRepository
{
public ICommunity GetByEmailAddress(string address)
{
var id = new UserIden { Email = address };
return ManageProvider.GetProxy<ICommunity>(id);
}
}
This will hide both the ManageProvider and the UserIden behind this abstraction, and allows you to replace it later on with something more useful and makes testing easier.
Registration now is very easy:
RegisterType<ICommunityRepository, ManageProviderCommunityRepository>();
Instead of calling myContainer.Resolve (as you do in your example), inject the dependencies in your classes. This prevents you from using the Service Locator anti-pattern.
Perhaps you could do something like this, using the InjectionFactory:
myContainer.RegisterType<ICommunity>(
new InjectionFactory(c => ManageProvider.GetProxy<ICommunity>(new UserIden {Email = "test#test.com"})));
var classReturned = myContainer.Resolve<ICommunity>();
... Though you wouldn't be able to pass the UserIden as a parameter to the Resolve call, so I'm not sure if this is what you want.
To register all the public classes of the assembly you could perhaps iterate over Assembly.GetTypes() and register them in the same way?

Categories

Resources