简体   繁体   中英

How can I get the instance of a interface from Unity?

I registered

container.RegisterType<IService, MyService>();

I want to create a helper class similar to

public class MyHelper
{
    private IService _service;

    public void SomeMethod
    {
        _service.RunSomething();
    }
}

I really wish this _serivce just magically maps to MyService constructor and not be null, as I have no where to find an IService or Service instance anywhere else.

How can I make this _service self mapped according to Unity mapping?

You still have to assign the injected IService to your instance. This is usually done via the constructor:

public class MyHelper {
    private readonly IService _service;

    public MyHelper(IService service) {
        _service = service;
    }

    public void SomeMethod() {
        // _service isn't null anymore
    }
}

Edit: looking at your comment I don't think you're using IoC correctly so I'm going to try to fill in some gaps. You don't want to create new instances of MyHelper beacuse whatever creates it will have to have knowledge of IService and any other dependencies MyHelper introduces. Instead, you can create a factory that handles creating new instances of MyHelper which will also handle its dependencies. This way, you can set up IoC to resolve dependencies on this factory.

public interface IInstanceFactory<out T> {
    T Create();
}

public class MyHelperFactory : IInstanceFactory<MyHelper> {
    private readonly Func<MyHelper> _myHelperFactory;

    public MyHelperFactory(Func<MyHelper> myHelperFactory) {
        _myHelperFactory = myHelperFactory;
    }

    public MyHelper Create() {
        return _myHelperFactory();
    }
}

So we now have a factory that stores a Func which is used to create an instance of MyHelper . All it's doing is executing the function that we will define in the IoC setup. All that function does is return a new instance of MyHelper .

Now we can set up IoC to handle everything else for us. So in your IoC setup you'd do the following (I don't know Unity so I'm going to show you using Autofac. Unity should be capable of doing everything I'm showing.)

Register the service:

container.RegisterType<MyService>().As<IService>();

Register the factory: (this is where the magic happens)

container.Resolve(b => {
    var service = b.Resolve<IService>();
    var myHelperFactory = new Func<MyHelper>(() => new MyHelper(service));

    return new MyHelperFactory(myHelperFactory);
}).As<IInstanceFactory<MyHelper>>();

Here we get an instance of IService which we already registered as MyService . Then we create a Func<MyHelper> who just creates a new instance of MyHelper and passes along the IService instance we just resolved. Lastly, we return a new MyHelperFactory and pass the Func<MyHelper> into the factory.

So lets say we have the class Foo . And Foo needs to create an instance of MyHelper without having any knowledge of MyHelper's dependencies:

public class Foo {
    private readonly IMyHelperFactory _factory;

    public Foo(IMyHelperFactory factory) {
        _factory = factory;
    }

    public void MethodThatCreatesMyHelper() {
        var instance = _factory.Create();
        // you now have a valid instance of `MyHelper`
    }
}

The last thing you would do is resolve Foo from your container (as long as you set it up):

var fooInstance = container.Resolve<Foo>();

fooInstance.MethodThatCreatesMyHelper();

And here is a gist of my example above. The point to take away is that Foo can create an instance MyHelper without having any knowledge of its dependencies.

One technique is to initialize MyHelper with an object that builds an IService object in the constructor. This can be as simple as a lambda expession:

public class MyHelper : IMyHelper
{
    private Func<IService> _serviceBuilderFunc;

    public MyHelper(Func<IService> serviceBuilderFunc)
    {
        _serviceBuilderFunc = serviceBuilderFunc;
    }

    public void SomeMethod()
    {
        var svc = _serviceBuilderFunc();
        svc.RunSomething();
    }
}

Then in your unity container configuration use the overload of RegisterType() to specify constructor parameters:

var serviceBuilderFunc = () => new MyService();
container.RegisterType<IMyHelper, MyHelper>(
    new InjectionConstructor(serviceBuilderFunc));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM