如何在C#中基于层次结构接口初始化对象

时间:2019-02-06 02:40:22

标签: c# .net

我有一个接口ICommandHandler ,其中TCommand的类型为ICommand(另一个接口)。 SomeWorkProcessCommandHandler类实现ICommandHandler。

我无法做的是将SomeWorkProcessCommandHandler类传递给另一个需要在其构造函数中使用ICommandHandler的类

在下面的代码中,Manager类在其构造函数中期望ICommandHandler 。传递someWorkProcessCommandHandler对象时出现编译时错误。如果我强制转换,则会出现运行时异常。

如何在构造函数中传递someWorkProcessCommandHandler对象?

请不要告诉我将其从构造函数中删除,并在Execute方法中找出处理程序。我不是要这么做。我要在这里唯一说明的是如何传递具有层次结构接口的对象

    public interface ICommand
    {
    }

    public interface ICommandHandler<TCommand> where TCommand : ICommand
    {
        void Handle(TCommand command);
    }

    public class SomeWorkProcessCommand : ICommand
    {
    }

    public class SomeWorkProcessCommandHandler : ICommandHandler<SomeWorkProcessCommand>
    {
        public void Handle(SomeWorkProcessCommand command)
        {
            Console.WriteLine("Some work Process Command Handler ");
        }
    }

    public class Manager 
    {
        private readonly ICommandHandler<ICommand> handler;

        public Manager(ICommandHandler<ICommand> handler)
        {
            this.handler = handler;
        }

        public void Execute(ICommand command)
        {

            handler.Handle(command);
        }

    }


    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            var someWorkProcessCommandHandler = new SomeWorkProcessCommandHandler();
            someWorkProcessCommandHandler.Handle(new SomeWorkProcessCommand());// This line works fine if the below code is not present

            //var manager = new Manager(someWorkProcessCommandHandler);  //Compile time error
            var manager = new Manager((ICommandHandler<ICommand>)someWorkProcessCommandHandler); //Runtime error after casting
            manager.Execute(new SomeWorkProcessCommand());

            Console.ReadKey();
        }
    }

2 个答案:

答案 0 :(得分:2)

问题出在您的Manager类设计中。您也应该在那里使用泛型。这是更新的代码,它可以正常工作:

public interface ICommand
{
}

public interface ICommandHandler<TCommand> where TCommand : ICommand
{
    void Handle(TCommand command);
}

public class SomeWorkProcessCommand : ICommand
{
}

public class SomeWorkProcessCommandHandler : ICommandHandler<SomeWorkProcessCommand>
{
    public void Handle(SomeWorkProcessCommand command)
    {
        Console.WriteLine("Some work Process Command Handler ");
    }
}

public class Manager<TCommandHandler, TCommand>
    where TCommandHandler : ICommandHandler<TCommand>
    where TCommand : ICommand
{
    private readonly TCommandHandler handler;

    public Manager(TCommandHandler handler)
    {
        this.handler = handler;
    }

    public void Execute(TCommand command)
    {
        handler.Handle(command);
    }
}


class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        var someWorkProcessCommandHandler = new SomeWorkProcessCommandHandler();
        someWorkProcessCommandHandler.Handle(new SomeWorkProcessCommand());// This line works fine if the below code is not present

        var manager = new Manager<SomeWorkProcessCommandHandler, SomeWorkProcessCommand>(someWorkProcessCommandHandler);  //Works now
        manager.Execute(new SomeWorkProcessCommand());

        Console.ReadKey();
    }
}

希望它可以解决您的问题。

答案 1 :(得分:2)

通过@tanveery补充答案,Manager类实际上只需要对传递到ICommandHandler<>的类型参数进行类型约束:

public class Manager<TCommand> where TCommand : ICommand
{
    private readonly ICommandHandler<TCommand> handler;

    public Manager(ICommandHandler<TCommand> handler)
    {
        this.handler = handler;
    }

    public void Execute(TCommand command)
    {
        handler.Handle(command);
    }
}

这将使用站点减少到:

var manager = new Manager<SomeWorkProcessCommand>(someWorkProcessCommandHandler);
manager.Execute(new SomeWorkProcessCommand());

更进一步,您可以通过创建静态工厂方法来完全消除在使用站点上指定类型参数的需要,例如:

public static class ManagerFactory
{
    public static Manager<TCommand> Create<TCommand>(ICommandHandler<TCommand> handler)
        where TCommand : ICommand => new Manager<TCommand>(handler);
}

使用站点将如下所示:

var manager = ManagerFactory.Create(someWorkProcessCommandHandler);
manager.Execute(new SomeWorkProcessCommand());