首先在Ninject中执行初始化

时间:2016-04-05 10:42:25

标签: c# ninject

我有这样的界面

public interface IPerson { }

实施

public class Fireman : IPerson
{
    public string Name { get; set; }
    public bool WithAssignedTruck { get; set; }
    ...
}

public class Pilot : IPerson
{
    public string Name { get; set; }
    public int Age { get; set; }
    ...
}

并将它们传递给构造函数

public class Registration : IRegistration
{
    private readonly Fireman _fireman;
    private readonly Pilot _pilot;

    public Registration(Pilot pilot, Fireman fireman)
    {
         this._fireman = fireman;
         this._pilot = pilot;
    }    
}

以下是初始化方法的样子。

public T PopulateProfile<T>() where T : IPerson, new()
{
    var personProfile = Activator.CreateInstance<T>();
    ...

    return personProfile;
}

请注意,此代码只是一个示例。

我有一个方法可以设置来自数据库的这些类的每个属性的值。我需要做的是,当我向Ninject询问任何实现 IPerson 接口的类时,Ninject应首先执行该方法,因此,Ninject将返回一个初始化类。希望你能帮我一臂之力。谢谢。

1 个答案:

答案 0 :(得分:0)

您可以将Ninject.Extensions.Conventions与生成IBindingGenerator绑定的ToMethod结合使用:

BindingGenerator

internal class PersonBindingGenerator : IBindingGenerator
{
    private static readonly MethodInfo PopulateOpenGenericMethodInfo =
        typeof(IProfileService).GetMethod("PopulateProfile");

    public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(
        Type type,
        IBindingRoot bindingRoot)
    {
        yield return bindingRoot
            .Bind(type)
            .ToMethod(x => CreatePerson(x.Kernel.Get<IProfileService>(), type));
    }

    private static object CreatePerson(
        IProfileService profileService,
        Type type)
    {
        var closedGeneric = PopulateOpenGenericMethodInfo.MakeGenericMethod(type);
        return closedGeneric.Invoke(profileService, new object[0]);
    }
}

绑定

kernel.Bind<IProfileService>().To<ProfileService>();

kernel.Bind(s => s
    .FromThisAssembly()
    .IncludingNonePublicTypes()
    .SelectAllClasses()
    .InheritedFrom<IPerson>()
    .BindWith<PersonBindingGenerator>());

测试

完整的测试代码供参考。

using FluentAssertions;
using Ninject;
using Ninject.Extensions.Conventions;
using Ninject.Extensions.Conventions.BindingGenerators;
using Ninject.Syntax;
using System;
using System.Collections.Generic;
using System.Reflection;
using Xunit;

namespace NinjectTest.SO36424126
{
    public interface IPerson
    {
        string SomeValue { get; set; }
    }

    class BarPerson : IPerson
    {
        public string SomeValue { get; set; }
    }

    class FooPerson : IPerson
    {
        public string SomeValue { get; set; }
    }

    public interface IProfileService
    {
        T PopulateProfile<T>() 
            where T : IPerson, new();
    }

    internal class ProfileService : IProfileService
    {
        public T PopulateProfile<T>()
            where T : IPerson, new()
        {
            var personProfile = Activator.CreateInstance<T>();
            personProfile.SomeValue = "initialized";
            return personProfile;
        }
    }

    internal class PersonBindingGenerator : IBindingGenerator
    {
        private static readonly MethodInfo PopulateOpenGenericMethodInfo = typeof(IProfileService).GetMethod("PopulateProfile");

        public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
        {
            yield return bindingRoot
                .Bind(type)
                .ToMethod(x => CreatePerson(x.Kernel.Get<IProfileService>(), type));
        }

        private static object CreatePerson(IProfileService profileService, Type type)
        {
            var closedGeneric = PopulateOpenGenericMethodInfo.MakeGenericMethod(type);
            return closedGeneric.Invoke(profileService, new object[0]);
        }
    }

    public class Test
    {
        [Fact]
        public void Foo()
        {
            var kernel = new StandardKernel();

            kernel.Bind<IProfileService>().To<ProfileService>();

            kernel.Bind(s => s
                .FromThisAssembly()
                .IncludingNonePublicTypes()
                .SelectAllClasses()
                .InheritedFrom<IPerson>()
                .BindWith<PersonBindingGenerator>());

            kernel.Get<BarPerson>().SomeValue.Should().Be("initialized");
        }
    }
}