New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can I somehow achieve this with the MVC 6 DI? #322

Closed
SharpNoiZy opened this Issue Nov 11, 2015 · 17 comments

Comments

Projects
None yet
5 participants
@SharpNoiZy

I have some Ninject code that I want to transfer to the new Microsoft DI system.
Is this possible or still not supported with Beta 8?
And if it is not supported, is there a workaround?

kernel.Bind(x => x.
.FromAssembliesMatching("MyLib.dll")
.SelectAllClasses().InheritedFrom(typeof(IQueryHandler<,>))
.BindAllInterfaces());

And then this:

public class QueryDispatcher : IQueryDispatcher
{
    private readonly IKernel _kernel;

    public QueryDispatcher(IKernel kernel)
    {
        if (kernel == null)
        {
            throw new ArgumentNullException("kernel");
        }

        _kernel = kernel;
    }

    public async Task<TResult> Dispatch<TParameter, TResult>(TParameter query)
        where TParameter : IQuery
        where TResult : IQueryResult
    {
        // Find the appropriate handler to call from those registered with Ninject based on the type parameters
        var handler = _kernel.Get<IQueryHandler<TParameter, TResult>>();
        return await handler.Retrieve(query);
    }
} 

The line:

var handler = _kernel.Get<IQueryHandler<TParameter, TResult>>();

is here important.
The Microsoft DI solution has no "kernel", right?

Kind regards

@Eilon

This comment has been minimized.

Show comment
Hide comment
@Eilon

Eilon Nov 11, 2015

Member

@SharpNoiZy I don't know if there's support for Ninject yet with ASP.NET 5's new DI system. There's are ways to wire up StructureMap and Autofac - see the links in the readme here: https://github.com/aspnet/DependencyInjection (we just updated it).

As far as there being a 'kernel' in the default DI system, I suppose the answer is no. The system assumes you register all services explicitly.

Member

Eilon commented Nov 11, 2015

@SharpNoiZy I don't know if there's support for Ninject yet with ASP.NET 5's new DI system. There's are ways to wire up StructureMap and Autofac - see the links in the readme here: https://github.com/aspnet/DependencyInjection (we just updated it).

As far as there being a 'kernel' in the default DI system, I suppose the answer is no. The system assumes you register all services explicitly.

@Eilon Eilon closed this Nov 11, 2015

@Eilon Eilon added the question label Nov 11, 2015

@SharpNoiZy

This comment has been minimized.

Show comment
Hide comment
@SharpNoiZy

SharpNoiZy Nov 12, 2015

Hi @Eilon
I think there was a missunderstanding, my intention was to use ONLY the new DI System and remove Ninject from my project.

But this is not possible with the above requirements?

Hi @Eilon
I think there was a missunderstanding, my intention was to use ONLY the new DI System and remove Ninject from my project.

But this is not possible with the above requirements?

@Eilon Eilon reopened this Nov 12, 2015

@Eilon

This comment has been minimized.

Show comment
Hide comment
@Eilon

Eilon Nov 12, 2015

Member

Not sure exactly what the scenario is. Can you elaborate more on what you want to do?

In the default DI system you can of course register types of services as well as implementations of those services (or factories for the service implementations). You can also register generic services.

Member

Eilon commented Nov 12, 2015

Not sure exactly what the scenario is. Can you elaborate more on what you want to do?

In the default DI system you can of course register types of services as well as implementations of those services (or factories for the service implementations). You can also register generic services.

@SharpNoiZy

This comment has been minimized.

Show comment
Hide comment
@SharpNoiZy

SharpNoiZy Nov 12, 2015

In the first code snipped is just a convient way to bind all generic interfaces of type IQueryHandler<,> to their correct handler classes.

And in the second snippet the line

var handler = _kernel.Get<IQueryHandler<TParameter, TResult>>();

Gets from the DI System the correct handler class with the generic type.
I just know the constructor injection of the Microsoft DI system, but I can't use this in this scenario because of the generic parameters.

So, those two things are what I don't know how to to with Microsoft DI system.
If I know that, I can remove Ninject from my project.

In the first code snipped is just a convient way to bind all generic interfaces of type IQueryHandler<,> to their correct handler classes.

And in the second snippet the line

var handler = _kernel.Get<IQueryHandler<TParameter, TResult>>();

Gets from the DI System the correct handler class with the generic type.
I just know the constructor injection of the Microsoft DI system, but I can't use this in this scenario because of the generic parameters.

So, those two things are what I don't know how to to with Microsoft DI system.
If I know that, I can remove Ninject from my project.

@khellang

This comment has been minimized.

Show comment
Hide comment
@khellang

khellang Nov 12, 2015

Contributor

This is kinda what's being discussed in #76, but with a bit more magic. It's not supported today. I know there's several other issues where people've requested some of the same functionality, coming from other containers.

Contributor

khellang commented Nov 12, 2015

This is kinda what's being discussed in #76, but with a bit more magic. It's not supported today. I know there's several other issues where people've requested some of the same functionality, coming from other containers.

@SharpNoiZy

This comment has been minimized.

Show comment
Hide comment
@SharpNoiZy

SharpNoiZy Nov 12, 2015

It sounds that you refering to point one of my post, let's say I do it in mean time manuelly for every type until this feature is somehow implemented.

But how do I resolve point two?

It sounds that you refering to point one of my post, let's say I do it in mean time manuelly for every type until this feature is somehow implemented.

But how do I resolve point two?

@khellang

This comment has been minimized.

Show comment
Hide comment
@khellang

khellang Nov 12, 2015

Contributor

@SharpNoiZy I have this working on a local branch:

public static class Program
{
    public static void Main()
    {
        var services = new ServiceCollection();

        services.Scan(scan => scan
            .FromAssembly(typeof(Program).GetTypeInfo().Assembly)
                .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>)))
                    .AsImplementedInterfaces()
                    .WithScopedLifetime());

        var provider = services.BuildServiceProvider();

        var queryHandler = provider.GetService<IQueryHandler<TestQuery, int>>();

        var result = queryHandler.Handle(new TestQuery()).Result; // Works, yay!
    }

    public class TestQuery { }

    public interface IQueryHandler<TQuery, TResult>
    {
        Task<TResult> Handle(TQuery query);
    }

    public class TestQueryHandler : IQueryHandler<TestQuery, int>
    {
        public Task<int> Handle(TestQuery query)
        {
            return Task.FromResult(0);
        }
    }
}

Would you be interested in something like that?

Contributor

khellang commented Nov 12, 2015

@SharpNoiZy I have this working on a local branch:

public static class Program
{
    public static void Main()
    {
        var services = new ServiceCollection();

        services.Scan(scan => scan
            .FromAssembly(typeof(Program).GetTypeInfo().Assembly)
                .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>)))
                    .AsImplementedInterfaces()
                    .WithScopedLifetime());

        var provider = services.BuildServiceProvider();

        var queryHandler = provider.GetService<IQueryHandler<TestQuery, int>>();

        var result = queryHandler.Handle(new TestQuery()).Result; // Works, yay!
    }

    public class TestQuery { }

    public interface IQueryHandler<TQuery, TResult>
    {
        Task<TResult> Handle(TQuery query);
    }

    public class TestQueryHandler : IQueryHandler<TestQuery, int>
    {
        public Task<int> Handle(TestQuery query)
        {
            return Task.FromResult(0);
        }
    }
}

Would you be interested in something like that?

@SharpNoiZy

This comment has been minimized.

Show comment
Hide comment
@SharpNoiZy

SharpNoiZy Nov 12, 2015

Yes, very interessted! :)
Looks like exactly what I searched for! 👍

Yes, very interessted! :)
Looks like exactly what I searched for! 👍

@SharpNoiZy

This comment has been minimized.

Show comment
Hide comment
@SharpNoiZy

SharpNoiZy Nov 13, 2015

Hi @khellang

How can I get your version?

Kind regards

Hi @khellang

How can I get your version?

Kind regards

@khellang

This comment has been minimized.

Show comment
Hide comment
@khellang

khellang Nov 13, 2015

Contributor

@SharpNoiZy I'll push the code later tonight (CET). I'll ping you.

Contributor

khellang commented Nov 13, 2015

@SharpNoiZy I'll push the code later tonight (CET). I'll ping you.

@SharpNoiZy

This comment has been minimized.

Show comment
Hide comment

THX!

@khellang

This comment has been minimized.

Show comment
Hide comment
@khellang

khellang Nov 14, 2015

Contributor

@SharpNoiZy I've pushed what I have now to https://github.com/khellang/Scrutor. There's also a NuGet package at https://www.nuget.org/packages/Scrutor. I'm working on getting some XML docs etc in there.

Contributor

khellang commented Nov 14, 2015

@SharpNoiZy I've pushed what I have now to https://github.com/khellang/Scrutor. There's also a NuGet package at https://www.nuget.org/packages/Scrutor. I'm working on getting some XML docs etc in there.

@SharpNoiZy

This comment has been minimized.

Show comment
Hide comment
@SharpNoiZy

SharpNoiZy Nov 16, 2015

Thx!
It's a pitty that you are no Microsoft Dev, so that they include your functions into the default package!
Please keep your package up to date at least to the final release of MvC 6 :)

Thx!
It's a pitty that you are no Microsoft Dev, so that they include your functions into the default package!
Please keep your package up to date at least to the final release of MvC 6 :)

@danroth27 danroth27 closed this Nov 16, 2015

@danroth27

This comment has been minimized.

Show comment
Hide comment
@danroth27

danroth27 Nov 16, 2015

Member

We don't have any plans to include this functionality in the default container. The default container is deliberately minimalistic. For a full featured container you can use any of the various existing containers.

Member

danroth27 commented Nov 16, 2015

We don't have any plans to include this functionality in the default container. The default container is deliberately minimalistic. For a full featured container you can use any of the various existing containers.

@BeardedOneMan

This comment has been minimized.

Show comment
Hide comment
@BeardedOneMan

BeardedOneMan Apr 15, 2016

@khellang I've tried follwing:

services.Scan(scan => scan.FromAssemblies(typeof(IQueryHandler<,>).Assembly) .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>))) .AsImplementedInterfaces() .WithScopedLifetime());

and it didn't register any QueryHandler. But for commands

services.Scan(scan => scan.FromAssemblies(typeof(ICommandHandler<>).Assembly) .AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<>))) .AsImplementedInterfaces() .WithScopedLifetime());

it works. Did I something wrong? I've tried following:

var queryTypes = typeof(IQuery<>) .GetTypeInfo() .Assembly.GetTypes() .Where(t => t.GetTypeInfo() != null && !t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsAbstract && t.GetTypeInfo().ImplementedInterfaces.Any(i => i.Name.Equals("IQuery1")));

        var handlerTypes = typeof(IQueryHandler<,>)
            .GetTypeInfo()
            .Assembly.GetTypes()
                .Where(t => t.GetTypeInfo() != null && !t.GetTypeInfo().IsInterface
                    && !t.GetTypeInfo().IsAbstract
                    && t.GetTypeInfo().ImplementedInterfaces.Any(i => i.Name.Equals("IQueryHandler`2")));

        var closedHandlers = queryTypes.Select(t => typeof(IQueryHandler<,>).MakeGenericType(t, t.GetTypeInfo().ImplementedInterfaces.First().GenericTypeArguments[0]));

        foreach (var closedHandler in closedHandlers)
        {
            // services.AddTransient(typeof(IQueryHandler<,>), closedHandler);
            var implementation = handlerTypes.FirstOrDefault(t => t.GetTypeInfo().ImplementedInterfaces.Any(i => i.FullName.Equals(closedHandler.FullName)));
            if (implementation != null)
            {
                // services.AddTransient(typeof(IQueryHandler<,>), implementation);
                services.AddTransient(closedHandler, implementation);
            }
        }`

and in the services collcetion It seems to me right, but resolve crashes. Is this possible without using some 3rd party container? Thx

@khellang I've tried follwing:

services.Scan(scan => scan.FromAssemblies(typeof(IQueryHandler<,>).Assembly) .AddClasses(classes => classes.AssignableTo(typeof(IQueryHandler<,>))) .AsImplementedInterfaces() .WithScopedLifetime());

and it didn't register any QueryHandler. But for commands

services.Scan(scan => scan.FromAssemblies(typeof(ICommandHandler<>).Assembly) .AddClasses(classes => classes.AssignableTo(typeof(ICommandHandler<>))) .AsImplementedInterfaces() .WithScopedLifetime());

it works. Did I something wrong? I've tried following:

var queryTypes = typeof(IQuery<>) .GetTypeInfo() .Assembly.GetTypes() .Where(t => t.GetTypeInfo() != null && !t.GetTypeInfo().IsInterface && !t.GetTypeInfo().IsAbstract && t.GetTypeInfo().ImplementedInterfaces.Any(i => i.Name.Equals("IQuery1")));

        var handlerTypes = typeof(IQueryHandler<,>)
            .GetTypeInfo()
            .Assembly.GetTypes()
                .Where(t => t.GetTypeInfo() != null && !t.GetTypeInfo().IsInterface
                    && !t.GetTypeInfo().IsAbstract
                    && t.GetTypeInfo().ImplementedInterfaces.Any(i => i.Name.Equals("IQueryHandler`2")));

        var closedHandlers = queryTypes.Select(t => typeof(IQueryHandler<,>).MakeGenericType(t, t.GetTypeInfo().ImplementedInterfaces.First().GenericTypeArguments[0]));

        foreach (var closedHandler in closedHandlers)
        {
            // services.AddTransient(typeof(IQueryHandler<,>), closedHandler);
            var implementation = handlerTypes.FirstOrDefault(t => t.GetTypeInfo().ImplementedInterfaces.Any(i => i.FullName.Equals(closedHandler.FullName)));
            if (implementation != null)
            {
                // services.AddTransient(typeof(IQueryHandler<,>), implementation);
                services.AddTransient(closedHandler, implementation);
            }
        }`

and in the services collcetion It seems to me right, but resolve crashes. Is this possible without using some 3rd party container? Thx

@khellang

This comment has been minimized.

Show comment
Hide comment
@khellang

khellang Apr 15, 2016

Contributor

@BeardedOneMan Can we move this discussion to https://github.com/khellang/Scrutor? 😄

Contributor

khellang commented Apr 15, 2016

@BeardedOneMan Can we move this discussion to https://github.com/khellang/Scrutor? 😄

@BeardedOneMan

This comment has been minimized.

Show comment
Hide comment
@BeardedOneMan

BeardedOneMan Apr 15, 2016

@khellang of course, sorry :)

@khellang of course, sorry :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment