我有这样的界面
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将返回一个初始化类。希望你能帮我一臂之力。谢谢。
答案 0 :(得分:0)
您可以将Ninject.Extensions.Conventions与生成IBindingGenerator
绑定的ToMethod
结合使用:
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");
}
}
}