C# 覆盖StructureMap 3中的自定义注册约定
我在最近的项目中使用了C# 覆盖StructureMap 3中的自定义注册约定,c#,generics,registration,ioc-container,structuremap,C#,Generics,Registration,Ioc Container,Structuremap,我在最近的项目中使用了CQRS模式,并将structuremap3用作我的IoC容器,因此我定义了以下转换来解析每个BaseEntity类型的icommandhelders: public class InsertCommandRegistrationConvention : StructureMap.Graph.IRegistrationConvention { private static readonly Type _openHandlerInterfaceType =
CQRS
模式,并将structuremap3
用作我的IoC容器
,因此我定义了以下转换来解析每个BaseEntity
类型的icommandhelders
:
public class InsertCommandRegistrationConvention
: StructureMap.Graph.IRegistrationConvention
{
private static readonly Type _openHandlerInterfaceType = typeof(ICommandHandler<>);
private static readonly Type _openInsertCommandType = typeof(InsertCommandParameter<>);
private static readonly Type _openInsertCommandHandlerType = typeof(InsertCommandHandler<>);
public void Process(Type type, Registry registry)
{
if (!type.IsAbstract && typeof(BaseEntity).IsAssignableFrom(type) &&
type.GetInterfaces().Any(x => x.IsGenericType &&
x.GetGenericTypeDefinition() == typeof(IAggregateRoot<>)))
{
Type closedInsertCommandType = _openInsertCommandType.MakeGenericType(type);
Type closedInsertCommandHandlerType =
_openInsertCommandHandlerType.MakeGenericType(type);
Type insertclosedHandlerInterfaceType =
_openHandlerInterfaceType.MakeGenericType(closedInsertCommandType);
registry.For(insertclosedHandlerInterfaceType)
.Use(closedInsertCommandHandlerType);
}
}
}
公共类InsertCommandRegistrationConvention
:StructureMap.Graph.i注册转换
{
私有静态只读类型_openHandlerInterfaceType=typeof(ICommandHandler);
私有静态只读类型_openInsertCommandType=typeof(InsertCommandParameter);
私有静态只读类型_openInsertCommandHandlerType=typeof(InsertCommandHandler);
公共作废进程(类型、注册表)
{
如果(!type.isastract&&typeof(BaseEntity).IsAssignableFrom(type)&&
type.GetInterfaces().Any(x=>x.IsGenericType&&
x、 GetGenericTypeDefinition()
{
类型closedInsertCommandType=\u openInsertCommandType.MakeGenericType(类型);
类型closedInsertCommandHandlerType=
_openInsertCommandHandlerType.MakeGenericType(类型);
类型insertclosedHandlerInterfaceType=
_openHandlerInterfaceType.MakeGenericType(closedInsertCommandType);
注册表.For(insertclosedHandlerInterfaceType)
.使用(closedInsertCommandHandlerType);
}
}
}
并在我的CompositionRoot中使用它:
public static class ApplicationConfiguration
{
public static IContainer Initialize()
{
ObjectFactory.Initialize(x =>
{
x.Scan(s =>
{
s.TheCallingAssembly();
s.WithDefaultConventions();
s.Convention<InsertCommandRegistrationConvention>();
});
});
return ObjectFactory.Container;
}
}
公共静态类应用程序配置
{
公共静态IContainer初始化()
{
ObjectFactory.Initialize(x=>
{
x、 扫描(s=>
{
s、 装配件();
s、 使用默认约定();
s、 公约();
});
});
返回ObjectFactory.Container;
}
}
因此,对于每个my实体,它都会注册相应的insertCommand处理程序
,例如它会注册
ICommandHandler
有时我需要为某些实体注册自定义的InsertCommandHandler
s,例如Product
我想为ICommandHandler
注册非通用的InsertProductCustomCommandHandler
类,而不是InsertCommandHandler
(换句话说,我想覆盖InsertCommendRegistrationConvention
)
使用Structuremap 3,我如何才能做到这一点?您可以使用方法
IContainer.Configure()
-通过Configure()
方法,您可以向现有的容器或ObjectFactory
添加其他配置
我已经简化了您的抽象,以实际证明这一点:
public abstract class BaseEntity { }
public interface ICommandHandler<T> { }
public class ClassA : BaseEntity { }
public class ClassB : BaseEntity { }
public class ClassC : BaseEntity { }
public class ClassD : BaseEntity { }
public class InsertCommandHandler<T> : ICommandHandler<T> { }
public class SpecialInsertDCommandHandler : ICommandHandler<ClassD> { }
此测试表明,配置了InsertCommandRegistrationConvention
的容器将为所有4个测试类ClassA
返回通用InsertCommandHandler
,以ClassD
[Test]
public void Handle_Initialize_RegistersClassesAToDToReturnInsertCommandHandler()
{
var container = ApplicationConfiguration.Initialize();
var resultA = container.GetInstance<ICommandHandler<ClassA>>();
var resultB = container.GetInstance<ICommandHandler<ClassB>>();
var resultC = container.GetInstance<ICommandHandler<ClassC>>();
var resultD = container.GetInstance<ICommandHandler<ClassD>>();
Assert.That(resultA.GetType() == typeof(InsertCommandHandler<ClassA>));
Assert.That(resultB.GetType() == typeof(InsertCommandHandler<ClassB>));
Assert.That(resultC.GetType() == typeof(InsertCommandHandler<ClassC>));
Assert.That(resultD.GetType() == typeof(InsertCommandHandler<ClassD>));
}
您可以修改约定,例如“如果有特定的命令处理程序,请使用它。否则,请使用InsertCommandHandler。”
看起来是这样的(就像qujck,我简化了类):
公共类InsertCommandRegistrationConvention:IRegistrationConvention
{
私有静态只读类型_openHandlerInterfaceType=typeof(ICommandHandler);
私有静态只读类型_openInsertCommandHandlerType=typeof(InsertCommandHandler);
私有静态只读IList_customCommandHandlerTypes;
静态插入命令和注册转换()
{
_CustomCommandHandlerType=\u openInsertCommandHandlerType
装配
.导出类型
.其中(x=>!x.IsAbstract)
.其中(x=>!x.IsGenericType | | x.GetGenericTypeDefinition()!=typeof(InsertCommandHandler))
.Where(x=>x.GetInterfaces().Any(i=>i.IsGenericType&&i.GetGenericTypeDefinition()==typeof(ICommandHandler)))
.ToArray();
}
公共作废进程(类型、注册表)
{
如果(!type.isastract&&typeof(BaseEntity).IsAssignableFrom(type))
{
var insertclosedHandlerInterfaceType=\u openHandlerInterfaceType.MakeGenericType(类型);
var closedInsertCommandHandlerType=\u openInsertCommandHandlerType.MakeGenericType(类型);
//检查是否有任何实现ICommandHandler的类也不是InsertCommandHandler
var customHandler=_customCommandHandlerTypes.FirstOrDefault(t=>t.GetInterfaces().Any(i=>i==insertclosedHandlerInterfaceType));
注册表.For(insertclosedHandlerInterfaceType)
.使用(customHandler??closedInsertCommandHandlerType);
}
}
}
我使用的类:
public abstract class BaseEntity { }
public class Class1 : BaseEntity { }
public class Class2 : BaseEntity { }
public class SpecialClass :BaseEntity { }
public interface ICommandHandler<T> { }
public class InsertCommandHandler<T> : ICommandHandler<T> { }
public class SpecialClassInsertCommandHandler : ICommandHandler<SpecialClass> { }
公共抽象类BaseEntity{}
公共类Class1:BaseEntity{}
公共类Class2:BaseEntity{}
公共类SpecialClass:BaseEntity{}
公共接口ICommandHandler{}
公共类InsertCommandHandler:ICommandHandler{}
公共类SpecialClassInsertCommandHandler:ICommandHandler{}
通过的测试:
Assert.That(ObjectFactory.GetInstance<ICommandHandler<Class1>>(), Is.InstanceOf<InsertCommandHandler<Class1>>());
Assert.That(ObjectFactory.GetInstance<ICommandHandler<Class2>>(), Is.InstanceOf<InsertCommandHandler<Class2>>());
Assert.That(ObjectFactory.GetInstance<ICommandHandler<SpecialClass>>(), Is.InstanceOf<SpecialClassInsertCommandHandler>());
Assert.That(ObjectFactory.GetInstance(),Is.InstanceOf());
Assert.That(ObjectFactory.GetInstance(),Is.InstanceOf());
Assert.That(ObjectFactory.GetInstance(),Is.InstanceOf());
优点是您修改了约定,而不是避免将其用于某些项目。如果您的逻辑需要更改,这会使所有内容保持在一个位置。我使用了container.Configure()
,但当我运行WhatDoIHave()时
,它显示了对于ICommandHandler
structuremap使用InsertCommandHandler
作为(默认)和自定义InsertCalendarCommandHandler
(但不是默认)。Hi@Masoud-我的代码以另一种方式显示它们,这有点令人费解-您添加了自定义注册表吗
public class InsertCommandRegistrationConvention : IRegistrationConvention
{
private static readonly Type _openHandlerInterfaceType = typeof (ICommandHandler<>);
private static readonly Type _openInsertCommandHandlerType = typeof (InsertCommandHandler<>);
private static readonly IList<Type> _customCommandHandlerTypes;
static InsertCommandRegistrationConvention()
{
_customCommandHandlerTypes = _openInsertCommandHandlerType
.Assembly
.ExportedTypes
.Where(x => !x.IsAbstract)
.Where(x => !x.IsGenericType || x.GetGenericTypeDefinition() != typeof (InsertCommandHandler<>))
.Where(x => x.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ICommandHandler<>)))
.ToArray();
}
public void Process(Type type, Registry registry)
{
if (!type.IsAbstract && typeof (BaseEntity).IsAssignableFrom(type))
{
var insertclosedHandlerInterfaceType = _openHandlerInterfaceType.MakeGenericType(type);
var closedInsertCommandHandlerType = _openInsertCommandHandlerType.MakeGenericType(type);
// check for any classes that implement ICommandHandler<T> that are not also InsertCommandHandler<T>
var customHandler = _customCommandHandlerTypes.FirstOrDefault(t => t.GetInterfaces().Any(i => i == insertclosedHandlerInterfaceType));
registry.For(insertclosedHandlerInterfaceType)
.Use(customHandler ?? closedInsertCommandHandlerType);
}
}
}
public abstract class BaseEntity { }
public class Class1 : BaseEntity { }
public class Class2 : BaseEntity { }
public class SpecialClass :BaseEntity { }
public interface ICommandHandler<T> { }
public class InsertCommandHandler<T> : ICommandHandler<T> { }
public class SpecialClassInsertCommandHandler : ICommandHandler<SpecialClass> { }
Assert.That(ObjectFactory.GetInstance<ICommandHandler<Class1>>(), Is.InstanceOf<InsertCommandHandler<Class1>>());
Assert.That(ObjectFactory.GetInstance<ICommandHandler<Class2>>(), Is.InstanceOf<InsertCommandHandler<Class2>>());
Assert.That(ObjectFactory.GetInstance<ICommandHandler<SpecialClass>>(), Is.InstanceOf<SpecialClassInsertCommandHandler>());