2016-12-21 7 views
1

Das sind meine Klassen:Resolving Generic Interface mit 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(); 
     } 
    } 

und meine 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; 
} 

ich zu verwenden versucht:

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; 
} 

Aber ich bin immer Ausnahme in diese Linie:

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

als ich versuchte, manuell seine gearbeitet:

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

Ausnahme:

Der angeforderte Dienst ‚JahadServices.Business.Services.Command.ICommandHandler`1 [[JahadServices.Business.Dtos.Command .ICommandDtc, JahadServices.Business.Dtos, Version = 1.0.0.0, Kultur = neutral, PublicKeyToken = null]] 'wurde nicht registriert. Um diese Ausnahme zu vermeiden, registrieren Sie entweder eine Komponente, um den Service bereitzustellen, überprüfen Sie für die Service-Registrierung mit IsRegistered(), oder verwenden Sie die ResolveOptional() -Methode, um eine optionale Abhängigkeit aufzulösen.

+0

Was ist der Typ ist TCommand hier '' 'var commandHandler2 = _container.Resolve >();' ''? Was implementiert '' 'IConnamdHandler ' ''? – tym32167

+0

@ tym32167 var obj = _scope.ResolveNamed (addFormDtc.SiteCollectionName); Obj in Runtime ist IntegerationCommand, aber , wenn ich an commandBus.Submit übergeben (Obj); Methode, es zu ICommandDtc konvertieren, ich weiß nicht, warum –

+0

versuchen, als '' 'commandBus übergeben.Submit (Obj as IntegerationCommand) '' ' – tym32167

Antwort

0

Sie versuchen ICommandHandler<ICommandDtc> zu lösen, aber Sie nur ICommandHandler<IntegerationCommand> von dieser verschiedenen Arten

IntegerationCommandHandler : CommandBase<IntegerationCommand> 

aber ICommandHandler<ICommandDtc> und ICommandHandler<IntegerationCommand> ist registriert.

Update:

nahm ich Ihre ursprüngliche Lösung und folgende tat: dieses commandBus.Submit(obj); dieses

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

ersetzen Und es funktionierte :) Weitere Informationen hier Calling generic method with a type argument known only at execution time

Kleine Erklärung.

Wenn Sie die generische Methode (Submit) aufrufen, hängt der Typ innerhalb dieser Methode vom Typ des Variablenzeigers ab. In Ihrem Fall haben Sie die IntegerationCommand-Instanz innerhalb der Variablen mit dem Typ ICommandDtc gespeichert. Soo, wenn Sie Submit (ibj) aufrufen, war es wie Submit (ibj). Also, das war das erste Problem, dass Sie Methode mit falschen generischen Parameter aufgerufen haben. Ich habe gerade Reflection verwendet, um Submit mit dem richtigen generischen Parameter (Submit) aufzurufen.

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 für Replay @ tym32167 aber im Gegenzug commandBus.Submit (obj); kann nicht finden Methode senden –

+0

@AmarPotki updaaated – tym32167

+0

vielen Dank, seine Arbeit –