Wir waren mit einer eigenständigen Geschichte beginnen werde, nur damit Sie verstehen, warum: ich irgendwelche Aktionen behandeln wollen, die Daten gegen die gleiche Schnittstelle zu ändern: ICommand Es sind die Dinge, die da draußen genannt ICommandHandlers existieren das handle jeden Befehl, den ich will. Also, wenn ich einen CreatePersonCommand brauche, würde ich einen CreatePersonCommandHandler da draußen brauchen.RegisterOpenGeneric mit SimpleInjector löst falschen Typ
Also hier ist der Körper einer Konsolenanwendung, die dies veranschaulicht: (Erfordert Simple Injector)
// The e.g. CreatePersonCommand, with TResult being Person, as an example.
public interface ICommand<TResult>
{
}
//This handles the command, so CreatePersonCommandHandler
public interface ICommandHandler<in TCommand, out TResult>
where TCommand : ICommand<TResult>
{
TResult Handle(TCommand command);
}
// Imagine a generic CRUD set of operations here where we pass
// in an instance of what we need made
public class CreateBaseCommand<TModel> : ICommand<TModel>
{
public TModel ItemToCreate { get; set; }
}
public class DeleteBaseCommand<TModel> : ICommand<TModel>
{
public TModel ItemToDelete { get; set; }
}
public class CreateCommandBaseHandler<TModel>
: ICommandHandler<CreateBaseCommand<TModel>, TModel>
{
public TModel Handle(CreateBaseCommand<TModel> command)
{
// create the thing
return default (TModel);
}
}
public class DeleteCommandBaseHandler<TModel>
: ICommandHandler<DeleteBaseCommand<TModel>, TModel>
{
public TModel Handle(DeleteBaseCommand<TModel> command)
{
// delete the thing
return default(TModel);
}
}
public class Program
{
private static Container container;
static void Main(string[] args)
{
container = new Container();
// Order does not seem to matter, I've tried both ways.
container.RegisterOpenGeneric(typeof(ICommandHandler<,>),
typeof(DeleteCommandBaseHandler<>));
container.RegisterOpenGeneric(typeof(ICommandHandler<,>),
typeof(CreateCommandBaseHandler<>));
container.Verify();
// So I want to make the usual hello world
var commandToProcess = new CreateBaseCommand<string> { ItemToCreate = "hello world"};
// Send it away!
Send(commandToProcess);
}
private static void Send<TResult>(ICommand<TResult> commandToProcess)
{
//{CreateBaseCommand`1[[System.String,..."}
var command = commandToProcess.GetType();
//{Name = "String" FullName = "System.String"}
var resultType = typeof (TResult);
//"ICommandHandler`2[[CreateBaseCommand`1[[System.String,..."}
// so it's the right type here
var type = typeof(ICommandHandler<,>).MakeGenericType(command, resultType);
// This is where we break!
var instance = container.GetInstance(type);
// The supplied type DeleteCommandBaseHandler<String> does not implement
// ICommandHandler<CreateBaseCommand<String>, String>.
// Parameter name: implementationType
}
}
Also aus irgendeinem Grund SimpleInjector versucht immer, die DeleteCommandHandler<>
für die CreateBaseCommand<>
zu lösen, die ich habe. Auch hier spielt die Reihenfolge keine Rolle. Ich habe andere, closed-type, commandhandlers (und ihre jeweiligen Befehle), die nur ICommandHandler<,>
erben, die gut funktionieren.
Ich verbrachte eine ganze Weile damit, alle möglichen Arten der Registrierung zu durchlaufen, die ich von this konnte.
Der Fehler, den Sie angetroffen haben, ist wirklich ärgerlich. Ich habe gerade das gleiche Problem beim Schreiben eines Dekorators in einer meiner eigenen Anwendungen bekommen. Ich überlege, eine Patch-Version (2.3.6) zu veröffentlichen, um diesen Fehler zu beheben, anstatt auf den nächsten Minor (2.4) zu warten, da es in einigen Szenarien wirklich schwierig ist, diesen Fehler zu umgehen. – Steven
Das sind gute Nachrichten, ich habe mich nicht auf andere Fälle gefreut. –