2016-12-21 11 views
1

Это мои классы:Разрешающая Общий интерфейс с Autofac

public interface ICommandDtc{ 
     string Command { get; set; } 
     string Xml { get; set; } 
    } 
    public interface ICommandHandler<in TCommand> 
     where TCommand : ICommandDtc 
    { 
     CommandResult Execute(TCommand command); 
     Task<CommandResult> ExecuteAsync(TCommand command); 
    } 

    public class CommandResult 
    { 
     public string Description { get; set; } 
     public int Code { get; set; } 
    } 

    public interface ICommandBus{ 
    Task<CommandResult> SubmitAsync<TCommand>(TCommand command) where TCommand : ICommandDtc; 
    CommandResult Submit<TCommand>(TCommand command) where TCommand : ICommandDtc; 
    } 

    public class CommandBus : ICommandBus{ 
     private readonly ILifetimeScope _container; 
     public CommandBus(ILifetimeScope scope){ 
      _container = scope; 
     } 
     public async Task<CommandResult> SubmitAsync<TCommand>(TCommand command) 
      where TCommand : ICommandDtc{ 
      var commandHandler = _container.Resolve<ICommandHandler<TCommand>>(); 
      return await commandHandler.ExecuteAsync(command); 
     } 
     public CommandResult Submit<TCommand>(TCommand command) 
      where TCommand : ICommandDtc 
     { 
     **//its worked** 
      var commandHandler = _container.Resolve<ICommandHandler<IntegerationCommand>>(); 
     **//exception** 
      var commandHandler2 = _container.Resolve<ICommandHandler<TCommand>>(); 
      return commandHandler2.Execute(command); 
     } 
    } 

    public abstract class CommandBase<TCommand> : ICommandHandler<TCommand> 
     where TCommand : ICommandDtc{ 
     public async Task<CommandResult> ExecuteAsync(TCommand command){ 
      var commandResult = new CommandResult(); 
      try{ 
       commandResult = await InternalExecuteAsync(command); 
      } 

      catch (Exception exp){ 

      } 
      return commandResult; 
     } 
     public CommandResult Execute(TCommand command) 
     { 
      var commandResult = new CommandResult(); 
      try 
      { 
       commandResult = InternalExecute(command); 
      } 
      catch (Exception exp) 
      { 
      } 
      return commandResult; 
     } 

     protected abstract Task<CommandResult> InternalExecuteAsync(TCommand command); 
     protected abstract CommandResult InternalExecute(TCommand command); 
    }//sample class 1 
    public class IntegerationCommandHandler : CommandBase<IntegerationCommand> 
    { 
     protected override Task<CommandResult> InternalExecuteAsync(IntegerationCommand command){ 
      throw new System.NotImplementedException(); 
     } 
     protected override CommandResult InternalExecute(IntegerationCommand command){ 
      switch (command.Command) { 
       case "SendDocument": 
        return SendDocument(command.Xml); 
      } 
      return new CommandResult {Code = 5,Description = ""}; 
     } 
     private CommandResult SendDocument(string xml){ 
      throw new System.NotImplementedException(); 
     } 
    }//sample class 2 
public class SocialOperationCommandHandler : CommandBase<SocialOperationCommand> 
    { 
     protected override Task<CommandResult> InternalExecuteAsync(SocialOperationCommand command){ 
      throw new System.NotImplementedException(); 
     } 
     protected override CommandResult InternalExecute(SocialOperationCommand command){ 
      throw new System.NotImplementedException(); 
     } 
    } 

и мой Autofac:

public static IContainer InitializeBusiness() 
{ 
    if (_lifetimeScope != null) 
    { 
     _lifetimeScope.Dispose(); 
     _lifetimeScope = null; 
    } 
    ConfigureAutoMapper(); 
    var builder = new ContainerBuilder(); 
    builder.RegisterType<Bootstrapper>().AsSelf(); 
    var assemblies = Assemblies.GetBusinessAssemblies.ToArray(); 
    builder.RegisterAssemblyTypes(assemblies).AsImplementedInterfaces(); 
    builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(ICommandDtc))).Named<ICommandDtc>(x => x.Name); 

    builder.RegisterType<AutoFacValidatorFactory>().As<IValidatorFactory>(); 

    _container = builder.Build(); 
    return _container; 
} 

Я пытался использовать:

try 
{ 
    var addFormDtc=new AddFormDtc {CommandName = "SendDocument",SiteCollectionName = "IntegerationCommand",Xml = "1"}; 
    var obj = _scope.ResolveNamed<ICommandDtc>(addFormDtc.SiteCollectionName); 
    obj.Command = addFormDtc.CommandName; 
    obj.Xml = addFormDtc.Xml; 
    var commandBus = _scope.Resolve<ICommandBus>(); 
    return commandBus.Submit(obj); 
} 
catch (Exception ex){ 
    comandResult.Code = 0; 
    comandResult.Description = ex.Message; 
    return comandResult; 
} 

Но я получаю исключение в эта линия:

var commandHandler2 = _container.Resolve<ICommandHandler<TCommand>>(); 

, когда я попытался вручную его работал:

var commandHandler = _container.Resolve<ICommandHandler<IntegerationCommand>>(); 

исключение:

Запрошенная служба «JahadServices.Business.Services.Command.ICommandHandler`1 [[JahadServices.Business.Dtos.Command .ICommandDtc, JahadServices.Business.Dtos, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]] 'еще не зарегистрирован. Чтобы исключить это исключение , зарегистрируйте компонент для предоставления услуги, отметьте для регистрации услуги с использованием IsRegistered() или используйте метод ResolveOptional() для разрешения дополнительной зависимости.

+0

WHATS тип является TCommand здесь '' 'вар commandHandler2 = _container.Resolve >();' ''? Что реализует '' 'IConnamdHandler ' ''? – tym32167

+0

@ tym32167 var obj = _scope.ResolveNamed (addFormDtc.SiteCollectionName); obj in Runtime - IntegerationCommand, но , когда я перехожу к commandBus.Submit (obj); метод, он конвертируется в ICommandDtc, я не знаю, почему –

+0

пытается пройти как '' 'commandBus.Отправить (obj as IntegerationCommand) '' ' – tym32167

ответ

0

Вы пытаетесь решить ICommandHandler<ICommandDtc>, но вы зарегистрировали только ICommandHandler<IntegerationCommand> из этого

IntegerationCommandHandler : CommandBase<IntegerationCommand> 

но ICommandHandler<ICommandDtc> и ICommandHandler<IntegerationCommand> это разные типы.

Update:

Я принял ваше оригинальное решение и сделал следующее: заменить эту commandBus.Submit(obj); этим

commandBus.GetType().GetMethod(nameof(ICommandBus.Submit)) 
    .MakeGenericMethod(obj.GetType()) 
    .Invoke(commandBus, BindingFlags.Public, null, new[] { obj}, 
    CultureInfo.CurrentCulture); 

И это сработало :) Дополнительная информация здесь Calling generic method with a type argument known only at execution time

Малый объяснение.

Когда вы вызываете общий метод (Отправить), тип внутри этого метода зависит от типа указателя переменной. В вашем случае вы сохранили экземпляр IntegerationCommand внутри переменной с типом ICommandDtc. Су, когда вы вызываете Submit (ibj), это было похоже на Submit (ibj). Итак, это была начальная проблема, которую вы назвали методом с неправильным общим параметром. Я просто использовал отражение для вызова Submit с правильным общим параметром (Submit).

commandBus.GetType() 
.GetMethod(nameof(ICommandBus.Submit)) //<- getting Submit<> method 
    .MakeGenericMethod(obj.GetType()) //<- set generic parameter, 
             // so now it Submit<IntegerationCommand> 
    .Invoke(commandBus, BindingFlags.Public, null, new[] { obj}, //<- invoke method 
+0

ty для replay @ tym32167, но в ответ commandBus.Submit (obj); can not find Отправить метод –

+0

@AmarPotki updaaated – tym32167

+0

Большое вам спасибо, его работа –