简体   繁体   English

基于运行时参数类型的方法动态选择

[英]Dynamic selection of method based on runtime parameter type

I've seen similar questions/answers for this posted in the past, but mine differs slightly from the others that I've seen. 我在过去发现了类似的问题/答案,但我与其他人的看法略有不同。

Essentially, I have a common interface and several classes that implement/inherit from it. 从本质上讲,我有一个通用接口和几个实现/继承它的类。 Then, in a separate class, I have methods that must act upon objects given by the interface IObject. 然后,在一个单独的类中,我有一些方法必须对接口IObject给出的对象起作用。 However, each of them must be acted upon in different ways, hence why there is a separate declaration of the method for each concrete type that extends IObject. 但是,必须以不同的方式对它们中的每一个进行操作,因此为什么对于扩展IObject的每个具体类型都有单独的方法声明。

class IObject
{
    ...
}

class ObjectType1 : IObject
{
    ...
}

class ObjectType2 : IObject
{
    ...
}

class FooBar
{
    void Foo (ObjectType1 obj);
    void Foo (ObjectType2 obj);
}

Now, to me, one obvious solution is to take advantage of dynamic binding by placing the method Foo inside each individual class, which would automatically choose at runtime the correct Foo to execute. 现在,对我来说,一个明显的解决方案是通过将方法Foo放在每个单独的类中来利用动态绑定,这将在运行时自动选择要执行的正确Foo。 However, this is not an option here, because I am defining multiple models for how to act upon these objects, and I would rather encapsulate each individual model for handling objects in its own class, rather than stuff all of the models into the object classes. 但是,这不是一个选项,因为我定义了多个模型来处理这些对象,我宁愿封装每个单独的模型来处理它自己的类中的对象,而不是将所有模型填充到对象类中。

I found this post which shows how to use a dictionary to dynamically choose at runtime the correct method implementation. 我发现这篇文章展示了如何使用字典在运行时动态选择正确的方法实现。 I'm fine with this approach; 我对这种方法很好; however, suppose that I have to perform a dispatch like this once in every model. 但是,假设我必须在每个模型中执行一次这样的调度。 If I only have IObject and its concrete implementations, is there any way to generalize this approach so that I could call methods of any name based on the runtime type of the objects ? 如果我只有IObject及其具体实现,有没有办法概括这种方法,以便我可以根据对象的运行时类型调用任何名称方法?

I know this is probably an unclear question, but I would greatly appreciate any help. 我知道这可能是一个不明确的问题,但我非常感谢任何帮助。

The dynamic keyword is actually really good at this: dynamic关键字实际上非常擅长:

void Main()
{
    var foobar = new FooBar();
    foreach(IObject obj in new IObject[]{ new ObjectType1(), new ObjectType2()})
    {
        foobar.Foo((dynamic)obj);
    }   
    // Output:
    //  Type 1
    //  Type 2
}

class IObject
{
}

class ObjectType1 : IObject
{
}

class ObjectType2 : IObject
{
}

class FooBar
{
    public void Foo (ObjectType1 obj) {
        Console.WriteLine("Type 1");
    }
    public void Foo (ObjectType2 obj) {
        Console.WriteLine("Type 2");
    }
}

The code is super-simple, and it's got pretty decent performance . 代码非常简单, 性能相当不错

Maybe you want something very close to visitor patter . 也许你想要一些非常接近访客模式的东西。

If you just want to pick a method ( Foo ) of an object ( FooBar ) by argument type you can use reflection to get all methods with given name ( Foo ) and do manual match of argument based on type of object ( ObjectTypeX ) and choices of the argument. 如果您只想通过参数类型选择对象( FooBar )的方法( Foo ),可以使用反射来获取具有给定名称( Foo )的所有方法,并根据对象类型( ObjectTypeX )和选项进行参数的手动匹配这个论点。 Don't forget to handle derived classes properly. 不要忘记正确处理派生类。

To avoid paying cost of reflection on every call - cache results (ie by building/compiling en Expression tree). 避免支付每次调用的反射成本 - 缓存结果(即通过构建/编译表达式树)。

Note that Dictionary (actions for given method name indexed by type) approach will probably easier to support/debug to start with. 请注意,Dictionary(按类型索引的给定方法名称的操作)方法可能更容易支持/调试开始。 Later if you find it slow for you needs you may replace it with something more complicated like reflection. 如果你发现它的需求很慢,你可以用更复杂的东西来代替它。

you can just make one method that takes the interface type,then you check for the correcttype and cast it 你可以创建一个采用接口类型的方法,然后检查正确的类型并进行转换

ObjectType1 obj1 = new ObjectType1();

foo(obj1);

void foo(IObject fm)
        {
            ObjectType1 cls;
            if (fm is ObjectType1)
            {
                cls = fm as ObjectType1;
                cls.ID = 10;
                MessageBox.Show(cls.ID.ToString() + "    " + cls.GetType().ToString());
            } 
        }

thats because the classes implement IObject ,cls.ID is just an example you can put one property you implement. 因为这些类实现了IObject,cls.ID只是一个例子,你可以放置一个你实现的属性。 Please try it and let me know....best wishes. 请尝试一下,让我知道....最好的祝福。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM