Is there something like Unity for simple things that don't require an interface?

Maybe I'm abusing Unity, but here. I have several applications, both of which load the same assembly of plugins. All assemblies require a library, and I want them to have access to this library through Unity. However, in order to use Unity or any other IoC infrastructure, I would have to write an interface for this library. I will probably do this, but since the interface is really not needed for anything other than support for Unity, I am afraid that this means that I 1) skip the point or 2) use the framework incorrectly. If I avoid something that the DI offers me, then I will have to make the library class single, and then pass it to all the plugin constructors or through a public property, and I don't want to do this.

However, and nothing is implemented with Unity, I don’t get one more detail - although Unity will allow me to request the library via Resolve <>, my plugins should still have a link to Unity which is created in the main applications. So, this is the case when your only option is to pass the Unity link to all the plugins, but then it is convenient from this point, simply because you can use Unity to get all the other dependencies?

UPDATE

I realized that I missed this point, but I hope someone can clarify for me - I should not miss the link to Unity all over the world! I only need to create a container in my application and then register all types later. Then, when I create all my plugins, they should just magically use these registered interfaces, without any extra effort, right? In my case, my constructors should be parameterless, because my plugin loader cannot deal with arguments, in which case I will have to use property nesting to give them access to the interfaces, right?

OTHER UPDATE

I went ahead and tried Unity. I registered an instance of my class that all plugins need. I also know that in the end I will have a problem with my plugin loader, as they are without parameters (and I may need to pass a Unity link to it to make them work). However, at the moment I am directly creating a plugin, and I am doing this using the Resolve method. So, here is basically what the code looks like:

// app code ICandySettings _candy_settings = new CandySettings(); IUnityContainer unity = new UnityContainer().RegisterInstance<ICandySettings>( _candy_settings); CandyPlugin _plugin = unity.Resolve<Candy>(); // throws null reference exception, see below. // plugin code public class Candy { [Dependency] ICandySettings CandySettings { get; set; } ... public Candy() { CandySettings.GetSetting("box"); // CandySettings is null! why? Didn't Unity do this for me? } } 

So, my problem right now is that I would expect (given my limited knowledge) that Unity will automatically set the CandySettings plugin link to any instance registered through RegisterInstance, but it is not.

WORKING OPTION

If I skip the smoke and mirror material and just pass my UnityContainer to the plugin constructor, then I can call Unity.Resolve () to set the value of the CandySettings property, and everything works fine. I would really like to know why the [Dependency] attribute does not do what I thought. If I'm not mistaken, I don't need to pass Unity to every constructor in my plugin loader. I should just use Unity.Resolve (), and it will supposedly work if [Dependency] works. However, now I understand that everyone is talking about how to choose an IoC container, then force it to the entire development team.

MEF!

So far, MEF has won the battle for me. It's pretty simple, and the magic material for smoke and mirrors is great for my needs (for now). But I would still like to get Unity to work. It seems strange to me that for MEF I only need to compose the details, and everything else just falls into place, whereas I can not get Unity to simply enter the material automatically, and I need to solve everything through the Unity link everywhere. It may not be right.

More MEF

I like the idea that I can easily resolve multiple objects using MEF, but what about when I use a strategy template to dictate code behavior? Currently, it is as simple as changing a link from one implementation of behavior to another, and it just works. Does anyone do this with MEF? The correct way to do this is with ImportMany, and then use additional code to determine which behavior in the list should be triggered?

+4
source share
4 answers

If your requirements for nesting dependencies are insignificant (which of their sounds, they are), you can try MEF . It is lightweight and easy to use, and has the advantage of being within the framework directly in .NET 4, which means there are no additional deployment requirements if you ever upgrade to .NET 4.

In the interim, it was maintained at 3.5 through the Codeplex website.

MEF is good at this, as it can work on any type, not just interfaces.

If you want plugins to use the "library" provided by your application, you most likely will always need this library to be accessible and referenced by your plugins (or at least a set of base classes or APIs).

+2
source

Most IoC containers can display specific classes as well as interfaces, namely that using interfaces is considered the most suitable for development and testing.

If all you want to do is allow multiple generic types to be created, you might want to use them yourself with System.IServiceProvider. it's built-in, so you don’t need to cascade IoC dependencies to your consumer code.

 public class SomePlugin { public SomePlugin(IServiceProvider serviceProvider) { _foo = serviceProvider.GetService(typeof(IFoo)) as IFoo; } } 

Or you may have a single-user service locator, as in the Shared Services Locator Library

 public class SomePlugin { public SomePlugin() { _foo = ServiceLocator.Current.GetService(typeof(IFoo)) as IFoo; } } 

EDIT: Considering your updates, I suggest using BuildUp to introlate property dependencies with your plugin instances after they are created. See this article

 PluginInstance plugin = // already loaded from whatever you're already doing container.BuildUp<PluginInstance>(plugin); 
+2
source

Firstly, I have a singleton that contains a reference to an instance of the Unity container, so I don't need to pass it around.

Secondly, you can use unityContainer.RegisterInstance(myInstance); or unityContainer.RegisterType<MyClass, MyClass>();

0
source

The reason Unity is not working properly in the published example is because in

 [Dependency] ICandySettings CandySettings { get; set; } 

default availability is private. Unity requires the property to be publicly available (so that it can call setter).

In the latest version of Unity (error message / behavior may differ from the old version) using your published code, I get an exception: "The CandySettings property for the type ConsoleApplication32.Candy is not configurable."

However, now I understand that everyone is talking about how to choose. Then the IoC container will forcibly put all this on your development team.

Yes and no. Obviously, classes must be connected so that dependencies are correctly entered (hopefully in Root of Composition ). However, the application code does not (or should not) indicate a reference to the container (for example, using the DependencyAttribute attribute or passing to IUnityContainer). In the published example, this can be done by registering InjectionProperty for the Candy class:

 ICandySettings _candy_settings = new CandySettings(); IUnityContainer unity = new UnityContainer().RegisterInstance<ICandySettings>( _candy_settings); unity.RegisterType<Candy>(new InjectionProperty("CandySettings")); CandyPlugin _plugin = unity.Resolve<Candy>(); 

I (along with many others) also prefers to introduce dependencies in the constructor (constructor injection), in which case Unity will do the right thing and add the dependency to the constructor:

 public class Candy { public ICandySettings CandySettings { get; private set; } ... public Candy(ICandySettings candySettings) { this.CandySettings = candySettings; this.CandySettings.GetSetting("box"); } } 

The registration code will be the same as in the original question:

 ICandySettings _candy_settings = new CandySettings(); IUnityContainer unity = new UnityContainer().RegisterInstance<ICandySettings>(_candy_settings); var _plugin = unity.Resolve<Candy>(); // Everything is OK :) 
0
source

Source: https://habr.com/ru/post/1307079/


All Articles