我回到Autofac问题,尽管以非常类似的方式使用它超过一年,真的需要一些建议。
我选择通过属性选择加入。这次的不同之处在于其中一个注册使用IIndex根据LoginState枚举为手头的任务选择最合适的接口。该值通过属性提供。
你可以认为它是一个非常基本的基于Autofac的状态机。
由于选择加入,我有以下扩展方法,它通过属性和属性的值来获取类型:
public static class ContainerBuilderEnumerateAttributedTypes
{
#region EnumerateAttributedTypes(builder, action)
[DebuggerStepThrough]
public static void EnumerateAttributedTypes<TAttribute>(this ContainerBuilder builder,
Action<Type, TAttribute> action) where TAttribute : Attribute
{
var typesAndAttributes = Assembly
.GetExecutingAssembly()
.GetTypes()
.Where(type => type.GetCustomAttributes<TAttribute>(false).Any())
.Select(type => new { Type = type, Attribute = type.GetCustomAttributes<TAttribute>(false).First() });
foreach (var typeAndAtttribute in typesAndAttributes)
{
action(typeAndAtttribute.Type, typeAndAtttribute.Attribute);
}
}
#endregion
#region EnumerateAttributedTypes(builder, inherit, action)
[DebuggerStepThrough]
public static void EnumerateAttributedTypes<TAttribute>(this ContainerBuilder builder,
bool inherit, Action<Type, TAttribute> action) where TAttribute : Attribute
{
var typesAndAttributes = Assembly
.GetExecutingAssembly()
.GetTypes()
.Where(type => type.GetCustomAttributes<TAttribute>(inherit).Any())
.Select(type => new { Type = type, Attribute = type.GetCustomAttributes<TAttribute>(inherit).First() });
foreach (var typeAndAtttribute in typesAndAttributes)
{
action(typeAndAtttribute.Type, typeAndAtttribute.Attribute);
}
}
#endregion
}
在Global.asax.cs期间,我调用builder.RegisterModule,它调用builder.RegisterModule。
我在那里有以下内容:
public class LogicAutofacModule : Module
{
#region Load
protected override void Load(ContainerBuilder builder)
{
builder.EnumerateAttributedTypes<DispatcherAttribute>((type, attribute) =>
{
var @interface = type.GetInterfaces().First();
// ReSharper disable once ConvertToLambdaExpression
builder
.RegisterType(type)
.As(@interface);
});
builder.EnumerateAttributedTypes<LogicAttribute>((type, attribute) =>
{
var @interface = type.GetInterfaces().First();
// ReSharper disable once ConvertToLambdaExpression
builder
.RegisterType(type)
.Keyed(attribute.State, @interface)
.As(@interface);
});
}
#endregion
IDispatcher有两个实例:
IIndex<LoginState, ILogic<AuthenticateContext, AuthenticateResult>>
和
IIndex<LoginState, ILogic<AuthenticateIncurringChargeContext, AuthenticateIncurringChargeResult>> _handlers;
如果通过属性指定了LoginState(如果适用),则通过
[LogicDispatcher(LogicState.InvalidCredentials)]
和类似的。
无论我如何做到这一点,即使回到最基本的注册方式,我也得到了
中没有找到的构造函数。Autofac.Core.Activators.Reflection.DefaultConstructorFinder error message.
以前从未有过这个......请提供建议或询问更多信息。
事后补充......这是ILogic实现的一个例子:
[Logic(LoginState.InvalidAccount)]
public class AuthenticateInvalidAccount : ILogic<AuthenticateContext, AuthenticateResult>
{
#region Execute
public AuthenticateResult Execute(AuthenticateContext context, LoginResponse response)
{
return new AuthenticateResult
{
State = State.InvalidAccount
};
}
#endregion
}
调度员的一个实例:
[Dispatcher]
public class AuthenticateDispatcher : IDispatcher<AuthenticateContext, AuthenticateResult>
{
#region Fields
private readonly IIndex<LoginState, ILogic<AuthenticateContext, AuthenticateResult>> _handlers;
#endregion
#region Constructors
public AuthenticateDispatcher(IIndex<LoginState, ILogic<AuthenticateContext, AuthenticateResult>> handlers)
{
_handlers = handlers;
}
#endregion
#region Dispatch
public AuthenticateResult Dispatch(AuthenticateContext context)
{
var service = new AccountServiceClient();
var response = service.Invoke(client => client.Login(context.Username, context.Password));
var logic = _handlers[response.LoginState];
var result = logic.Execute(context, response);
return result;
}
#endregion
}
服务超级简单:
[ErrorHandled]
public class Service : IService
{
#region Fields
private readonly IDispatcher<AuthenticateContext, AuthenticateResult> _authenticateDispatcher;
private readonly IDispatcher<AuthenticateIncurringChargeContext, AuthenticateIncurringChargeResult> _authenticateIncurringChargeDispatcher;
#endregion
#region Constructor
public Service(
IDispatcher<AuthenticateContext, AuthenticateResult> authenticateDispatcher,
IDispatcher<AuthenticateIncurringChargeContext, AuthenticateIncurringChargeResult> authenticateIncurringChargeDispatcher)
{
_authenticateDispatcher = authenticateDispatcher;
_authenticateIncurringChargeDispatcher = authenticateIncurringChargeDispatcher;
}
#endregion
#region Authenticate
public AuthenticateResponse Authenticate(AuthenticateRequest request)
{
var context = request.Map<AuthenticateContext>();
var result = _authenticateDispatcher.Dispatch(context);
var response = result.Map<AuthenticateResponse>();
return response;
throw new NotImplementedException();
}
#endregion
#region AuthenticateIncurringCharge
public AuthenticateIncurringChargeResponse AuthenticateIncurringCharge(AuthenticateIncurringChargeRequest request)
{
//var context = request.Map<AuthenticateIncurringChargeContext>();
//var result = _authenticateIncurringChargeDispatcher.Dispatch(context);
//var response = result.Map<AuthenticateIncurringChargeResponse>();
//return response;
throw new NotImplementedException();
}
#endregion
}
答案 0 :(得分:1)
相当尴尬。注释掉了注册逻辑服务的代码。惭愧:(
希望有人发现扩展方法很有用!