Я использую следующий интерфейс в своем логическом слое, чтобы обеспечить единоличную ответственность (можно сломать, но вам нужно перепрыгнуть через обручи и дать себе сильную головную боль для достижения этого).Autofac и перечисления с HasFlag
public interface ILogic<in TContext, out TOutput>
{
#region Execute
TOutput Execute(TContext context);
#endregion
}
Давайте предположим, что с иметь следующее:
[DataContract]
public class CompanyRequest : ExtensibleDataObject
{
#region Properties
[DataMember(IsRequired = true)]
public string Number { get; set; }
[DataMember(IsRequired = true)]
public Entity Entity { get; set; }
[DataMember(IsRequired = true)]
public CompanyOptions Options { get; set; }
#endregion
}
и
[DataContract]
public class CompanyResponse : ExtensibleDataObject
{
[DataMember]
public Company Company { get; set; }
// TODO: Store any errors occurred for graceful handling
//..
//..
}
Компания DataContract будет содержать данные, запрошенные через перечисление CompanyOptions, в конечном счете, будет 30 - 50 таких свойства.
Я понимаю, что Aufofac не может вводить список только логических экземпляров, необходимых при строительстве, но я знаю через IIndex, что можно заключить контракт с компанией или другое имя (для обсуждения сейчас) IIndex, хранящийся во время построения, либо с помощью метаданных, либо в противном случае он может, например, выполнить команду Where (registration => context.Flags.HasFlag (logic.Metadata.Flag), оставляя список логических реализаций, отвечающих за выполнение вызова. объяснение, вероятно, неправильное и полное отверстий)
Мой вопрос - это предпочтительный способ передачи этого типа поведения. В идеале я бы полностью избегал метаданных, поскольку я являюсь частью команды, задачей которой является введение пользовательский сервер nuget, через который мы рассматриваем и контролировать, какие пакеты команд разрешено использовать, поэтому для меня было бы иронично продолжать добавлять новые пакеты, такие как пакет Aufofac.Extras.Metadata.
Logic регистрация автоматическая/отказ в с помощью атрибута:
[Logic(Entity.Uk, CompanyDetail.PaymentTrends)]
public class PaymentTrends : ILogic<CompanyRequest, NullLogicResponse>
{
public NullLogicResponse Execute(CompanyRequest request)
{
throw new NotImplementedException();
}
}
Каждых сборок, которое регистрируется с Autofac делает это через модуль, как так:
public class LogicAutofacModule : Module
{
#region Load
protected override void Load(ContainerBuilder builder)
{
// ReSharper disable once IteratorMethodResultIsIgnored
builder.RegisterTypesWithAttribute<LogicAttribute>(typeof(ILogic<,>));
builder.RegisterAssemblyModules<DataAutofacModule>();
}
#endregion Load
}
Где RegiserTypesWithAttribute выглядит следующим образом:
public static class ContainerBuilderRegisterTypesWithAttribute
{
#region RegisterTypesWithAttribute
public static IEnumerable<IRegistrationBuilder<object, ConcreteReflectionActivatorData, SingleRegistrationStyle>> RegisterTypesWithAttribute<TAttribute>(this ContainerBuilder builder, Type typeBeingRegistered) where TAttribute : Attribute
{
var assembly = typeof(TAttribute).Assembly;
// ReSharper disable once LoopCanBeConvertedToQuery ... no thanks!
foreach (var type in assembly
.GetTypes()
.Where(type => type.HasCustomAttribute<TAttribute>()))
{
var registration = builder.RegisterType(type)
.As(type.GetInterfaces()
.First(i =>
i.IsGenericType &&
i.GetGenericTypeDefinition() == typeBeingRegistered));
yield return registration;
}
}
#endregion
}
Я еще не могу получить свою область головы вокруг наилучшего способа зарегистрируйте тип и его метаданные. LogicAttribute предоставляет свойство Metadata, состоящее из Entity и Flag. Ключ можно догадаться, что его можно исключить только для строк? так что я иду с IIndex <>, а затем обеспечить параметр моего конструктора выглядит примерно так:
public LogicDispatcher(IEnumerable>Lazy<Meta<LogicMetadata, ILogic<NullLogicResponse, CompanyRequest>>> logicEnumerable)
{
_logicEnumerable = logicEnumerable;
}
, а затем в пределах его Execute метода:
public NullLogicResponse Execute(CompanyRequest request)
{
var applicableLogic =
_logicEnumerable.Where(metadata => metadata.HasFlag(request.Flag);
foreach (var logic in applicableLogic)
{
logic.Execute(request)
}
}
Любая помощь по улучшению выше и/или лучший подход к решению этой проблемы будет с благодарностью оценен. Спасибо.
P.S.
Было бы 30 и растущих интерфейсов ILogic с одинаковыми типами. Каждый из них был бы/может быть запущен через TPL, например, поэтому я рад получить X-регистрацию сразу.
Ребята, я сформулировал это слишком плохо для вас, чтобы понять проблему? –