C# 有没有办法在运行时接受未知类型?

C# 有没有办法在运行时接受未知类型?,c#,oop,design-patterns,solid-principles,C#,Oop,Design Patterns,Solid Principles,我试图解决一个简单的OOPs问题。当我必须创建一些武器时,每种武器都有一个主要动作,而这个主要动作可以通过鼠标点击来执行。例如,一支猎枪正在射击,而卡塔纳正在挥动它。下面是我的班级 public interface IShootable { void TakeShot(); } public interface ISwingable { void Swing (); } public class ShotGun : IShootable { public void Ta

我试图解决一个简单的OOPs问题。当我必须创建一些武器时,每种武器都有一个主要动作,而这个主要动作可以通过鼠标点击来执行。例如,一支猎枪正在射击,而卡塔纳正在挥动它。下面是我的班级

public interface IShootable
{
    void TakeShot();
}
public interface ISwingable
{
    void Swing ();
}

public class ShotGun : IShootable
{
    public void TakeShot()
    {
    }
}
public class Kanata : ISwingable
{
    public void Swing ()
    {
    }
}   
每种武器都为其主要行动实施了不同的接口。我不确定是否可以创建一个抽象类,从中可以继承这些具体类。它似乎无法替代两种不同类型的武器

我想要实现的是,在运行时,当用户选择其中一种武器时,用户只需单击鼠标即可获得正确的操作。对于猎枪来说,它是射击,而对于武士刀来说,它是摇摆


我要做的就是接受它。或者我应该以其他方式重新构造类。

这两个类都可以使用攻击/使用方法实现第三个接口-IWeapon:

注意,这里有IWeapon接口。你不必明确地去做,而且仍然可以用正常的方式去做。但我更喜欢这样。这样,当你有一个Katana对象时,只有Swing是可见的,而不是攻击。我只是觉得让这两种方法都可见是令人困惑的


还请注意,IWeapon与ISwingable和IShootable无关,因为可摆动的东西网球拍和可射击的东西水枪不一定是武器。

这两个类都可以通过攻击/使用方法实现第三个接口-IWeapon:

注意,这里有IWeapon接口。你不必明确地去做,而且仍然可以用正常的方式去做。但我更喜欢这样。这样,当你有一个Katana对象时,只有Swing是可见的,而不是攻击。我只是觉得让这两种方法都可见是令人困惑的


另外请注意,IWeapon与ISwingable和IShootable无关,因为可摆动的东西、网球拍和可射击的东西、水枪不一定是武器。

您可能需要做一些更通用的事情:

public interface IWeaponPrimaryAction
{
    void PerformPrimaryAction();
}
public interface IWeaponAction
{
    void PrimaryAction();
}

public class Shoot :IWeaponAction
{
    public void PrimaryAction()
    {
        //Fire in the hole
    }
}   
public class Swing :IWeaponAction
{
    public void PrimaryAction()
    {
        //Into pieces
    }
}
public class ShotGun : IWeaponPrimaryAction
{
    private IWeaponAction _action = new Shoot();
    public void PerformPrimaryAction()
    {
        _action.PrimaryAction();
    }
}
public class Kanata : IWeaponPrimaryAction
{
    private IWeaponAction _action = new Swing();
    public void PerformPrimaryAction()
    {
        _action.PrimaryAction();
    }
}
比这更好的只是注入行动:

public class ShotGun : IWeaponPrimaryAction
{
    private IWeaponAction _action;
    public ShotGun(IWeaponAction action)
    {
        _action = action;
    }
    public void PerformPrimaryAction()
    {
        _action.PrimaryAction();
    }
}

您可能希望执行更通用的操作:

public interface IWeaponPrimaryAction
{
    void PerformPrimaryAction();
}
public interface IWeaponAction
{
    void PrimaryAction();
}

public class Shoot :IWeaponAction
{
    public void PrimaryAction()
    {
        //Fire in the hole
    }
}   
public class Swing :IWeaponAction
{
    public void PrimaryAction()
    {
        //Into pieces
    }
}
public class ShotGun : IWeaponPrimaryAction
{
    private IWeaponAction _action = new Shoot();
    public void PerformPrimaryAction()
    {
        _action.PrimaryAction();
    }
}
public class Kanata : IWeaponPrimaryAction
{
    private IWeaponAction _action = new Swing();
    public void PerformPrimaryAction()
    {
        _action.PrimaryAction();
    }
}
比这更好的只是注入行动:

public class ShotGun : IWeaponPrimaryAction
{
    private IWeaponAction _action;
    public ShotGun(IWeaponAction action)
    {
        _action = action;
    }
    public void PerformPrimaryAction()
    {
        _action.PrimaryAction();
    }
}

我的偏好是@Riki建议的,并创建一个接口,所有武器都用一个方法IWeapon.PerformPrimaryAction继承IWeapon。但是,如果您不喜欢,您可以创建一个所有武器接口都源自的基础接口,然后在运行时使用casting、is或as来确定您拥有的武器:

public interface IWeapon {};

public interface IShootable : IWeapon
{
    void TakeShot();
}

public interface ISwingable : IWeapon
{
    void Swing ();
}

public partial class YourGameClass
{
    public void DoTheAction (IWeapon weapon)
    {
        if (weapon is IShootable)
            (weapon as IShootable).TakeShot();
        if (weapon is ISwingable)
            (weapon as ISwingable).Swing();
    }
}

我的偏好是@Riki建议的,并创建一个接口,所有武器都用一个方法IWeapon.PerformPrimaryAction继承IWeapon。但是,如果您不喜欢,您可以创建一个所有武器接口都源自的基础接口,然后在运行时使用casting、is或as来确定您拥有的武器:

public interface IWeapon {};

public interface IShootable : IWeapon
{
    void TakeShot();
}

public interface ISwingable : IWeapon
{
    void Swing ();
}

public partial class YourGameClass
{
    public void DoTheAction (IWeapon weapon)
    {
        if (weapon is IShootable)
            (weapon as IShootable).TakeShot();
        if (weapon is ISwingable)
            (weapon as ISwingable).Swing();
    }
}

你需要知道一件武器在课外是可以摆动的还是可以射击的吗?如果没有,您可以只使用一个名为IWeapon的接口,该接口带有一个DoAttack或类似的更好的名称方法,而不是两个接口。您需要知道武器在类外是可摆动的还是可射击的吗?如果没有,您可以只使用一个名为IWeapon的接口,使用DoAttack或类似的更好的名称方法,而不是两个接口