将接口作为参数传递-需要实型. [英] Passing an Interface as a parameter - Need the real type.

查看:72
本文介绍了将接口作为参数传递-需要实型.的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我使用接口将使用该接口的对象传递给方法. (是的,我会用代码解释.)

我创建了一个服务管理器类,它看起来像这样.

Basically, I''m using an interface to pass objects which use that interface to a method. (Yeah, I''ll explain with code.)

I''ve created a service manager class, it looks like this.

public static class ServiceManager
{
    // Services
    private static Dictionary<Type, object> Services = new Dictionary<Type, object>();

    // Add Service (This is the working version thanks to the solution provided.)
    public static void AddService(object obj)
    {
        AddService(obj.GetType(), obj);
    }

    // Get Service
    public static T GetService<T>()
    {
        return (T)Services[typeof(T)];
    }
}



我使用接口而不是类类型将对象传递给以下方法. (这是我的ComponentManager类的一部分.)



I''m passing my object to the following method using my interface rather than my class type. (This is part of my ComponentManager class.)

public void Add(IGameComponent component)
{
    Components.Add(component);
    component.Initialize();
}



我想用这种方法将实际的类类型添加到我的服务管理器中,如下所示:.



I want to add the actual class type to my service manager in that method, like this..

public void Add(IGameComponent component)
{
    Type t = component.GetType();
    ServiceManager.AddService<t>(component);
    Components.Add(component);
    component.Initialize();
}



我已经尝试过我能想到的每个变体,即typeof,GetType,甚至还考虑使用System.Reflection,但无法弄清楚. (因此,简而言之,我需要将组件转换回其基本类型,以便在我的AddService调用中用作T.)

我希望我已经对此进行了充分的解释. (非常抱歉,这么快就发布了另一个问题.)

---

我只想添加,已经检查了Type t的结果,它的确获取了我的课程,但是,AddService拒绝接受它作为参数. (这是一个错误,还是在这种情况下需要特殊的方法?)



I''ve tried about every variation I can think of, typeof, GetType, I even looked into using System.Reflection, but couldn''t figure it out. (So, in short, I need to cast component back to it''s base type, for use as T in my AddService call.)

I hope I''ve explained this adequately. (And sorry about posting another question so soon.)

---

I just want to add, I''ve checked the results of Type t, and it does indeed get my class, however, AddService refuses to accept it as a parameter. (Is this a bug, or is there a special method needed in this case?)

推荐答案

都错了.您需要了解一些非常基本和非常简单的内容.

接口是实型.您需要了解有编译时类型运行时类型.接口只能是编译时类型,因为那里不能创建接口类型的对象.但是,接口引用可以表示一个真实的对象,只有此对象的运行时类型可以是实现该接口的某种结构或类.没有方法接口"之类的东西.类型转换是一件坏事,在大多数情况下可以避免.最后,您不应该尝试您能想到的所有变化".如果尝试了几次但都失败了,则说明您已经做错了.您需要了解事物,而不是获得一些行之有效"的结果.它可以正常工作",如果您不了解其操作方式,那么它实际上是行不通的.

基本上,这是您目前需要了解的所有内容,但是您需要很好地了解它.

现在,仅添加IGameComponent类型的组件.因此,您需要执行以下方法:

All wrong. You need to understand a number of very fundamental and pretty simple things.

Interface are real types. You need to understand that there are compile-time types and run-time types. Interfaces can be only compile-time types because there one cannot create an object of interface type. Nevertheless, interface reference can represent an real object, only the run-time type of this object can be some structure or class implementing the interface. There is no such thing as "interface to a method". Type casting is a bad thing and can be avoided in most cases. And finally, you should not "try about every variation you can think of". If you try couple of things and failed, you already are doing something wrong. You need to understand things, not to get some result which "just works". It something "just works", it does not really work if you don''t understand how.

Basically, this is pretty much all what you need to understand at this time, but you need to understand it well.

Now, you add only the components of the type IGameComponent. So, you need to following method:

public static class ServiceManager {
    // Services
    private static Dictionary<Type, object> Services = new Dictionary<Type, object>();

    // Add Service
    public static void AddService<T>(IGameComponent obj)
    {
        Services.Add(typeof(T), obj);
    }
}



现在,我不知道您的字典中该类型的目的.可能是,您需要一个运行时类型,因此它应该更简单:





Now, I don''t know the purpose of the type in your dictionary. Chances are, you need a run-time type, so it should be even simpler:



public static class ServiceManager {
    // Services
    private static Dictionary<Type, object> Services = new Dictionary<Type, object>();

    // Add Service
    public static void AddService(IGameComponent obj)
    {
        Services.Add(obj.GetType(), obj);
    }
}



-SA



—SA


如果Dictionary中的键始终是对象的具体类型,则不需要通用参数:
If the key in your Dictionary should always be the concrete type of the object than you don''t need the generic parameter:
// Add Service
public static void AddService(object obj)
{
    Services.Add(obj.GetType(), obj);
}


如果键有时"与实际对象不同,则应将通用参数转换为普通参数:


If the key is "sometimes" different from the actual object than you should convert the generic parameter into a normal parameter:

public static void AddService(Type t, object obj)
{
    Services.Add(t, obj);
}


解决方案面临的基本问题是,您想确定并使用运行时中标识的类型,但是泛型是编译时的魔术.

考虑一下,您可能应该重载函数:


The base problem your are facing with your solution is that you want to determine and use a type identified in runtime, but generics are compile time magic.

Thinking about it you should probably overload your function:

public static void AddService<t>(object obj)
{
    AddService(typeof(T), obj);
}
public static void AddService(object obj)
{
    AddService(obj.GetType(), obj);
}
public static void AddService(Type t, object obj)
{
    Services.Add(t, obj);
}</t>


现在您已经拥有了所有的东西:).


Now you have everything :).


一个有趣的问题,出于好奇,我投票赞成.

而且,我将对其进行深入"响应,因为您在此处处理的内容间接与我正在使用接口进行的一些实验有关:因此,尝试实施基于测试用例的方法对我来说具有内在的价值在您的想法上.

这些注释(对于一个标准的线程注释来说太长了,并且它们包含我想要以格式化的形式显示的代码)在这里提供不是因为我相信我对您的设计方案有一个解决方案" (我没有并不能假装完全理解它),但希望他们至少可以帮助澄清所提出的问题,或者对其他CP成员有所帮助.

马上想到的一件事是:由于您使用Type对象作为Dictionary的键:这意味着可以将一个Type添加到Dictionary中(您将获得如果您添加多个任何一个Type,则会出现重复的键错误.

如果每种类型只有一个实例:为什么在这里使用字典?

这对我提出了一个第二个问题:由于您希望每个对象实例一个词典条目(您现在正在为词典"中的值"参数传递对象实例):您不想使用字典< obj< T> ;,类型>)?

在这种情况下,"AddService现在可能看起来像:
An interesting question, which I''ve voted-up out of curiosity.

And, I''ll respond to it "in depth" because what you are dealing with here indirectly relates to some experiments I am doing with using interfaces: so it''s inherently of value to me to try and implement a test case based on your ideas.

These comments (too long for just a standard thread comment, and they include code which I want displayed formatted) are offered here not because I believe I have a "solution" for your design scenario (I don''t pretend to understand it fully), but with the hope they may, at least, contribute to clarification of the question asked, or be of some benefit to other CP members.

One thing that immediately comes to mind: is that since you are using a Type object as the key to a Dictionary: that means one-and-only-one Type is going be able to be added to the Dictionary (you''ll get a duplicate key error if you add more than one of any Type).

If there''s one-and-only-one instance of each Type: why use a Dictionary here ?

Which raises a secondary question, for me: since you want one Dictionary entry per instance of object (you are now passing in the objects'' instances for the ''Value argument in the Dictionary): don''t you want to use a Dictionary<obj<T>, Type>) ?

In which case ''AddService now might look like:
public static void AddService<T>(T obj)
{
    Services.Add(obj, typeof(T));
}

我确实使用此方法创建了一个简单的测试示例,在该示例中,我验证了它可以编译,并将其用于测试接口:

I did create a simple test example using this approach in which I verified that it would compile, using this for a test interface:

// must include these references to use this interface:
using System.Windows.Forms;
using System.Drawing;
//
public interface IWhatEver
{
    Size bSize { get; set;}
    Point bLoc { get; set; }
}

然后,我可以这样拨打电话;

Then, I could make a calls like this;

// the argument 'theMButton passed in here
// is an instance of a class that inherits from both Button and IWhatEver
private void AddModButton(IWhatEver theMButton)
{
    ServiceManager.AddService(theMButton);
}

在测试之前,我向ServiceManager类添加了一个方法,以公开服务字典:

Prior to testing, I added a method to the ServiceManager class, to expose the Services Dictionary:

public static Dictionary<object, Type> GetServices()
{
    return Services;
}

我用来测试此沙盒实验的代码是

The code I used to test this little sandbox experiment was

ServiceManager.AddService(new Button());
ServiceManager.AddService(new ModButton(bName: "inherited Button"));
ServiceManager.AddService(new TextBox());
ServiceManager.AddService(new ListBox());

ModButton mb2 = new ModButton(bName: "second inherited Button");
AddModButton(mb2 as IWhatEver);

IWhatEver mb3 = new ModButton(bName: "third inherited Button");
AddModButton(mb3);

然后,我检查了服务字典的内容,如下所示:

Then, I examined the contents of the Services Dictionary like this:

private void InspectServices()
{
    Console.WriteLine();

    foreach (var theKVP in ServiceManager.GetServices())
    {
        Console.WriteLine("object = " 
          + theKVP.Key.ToString() 
          + " : type = " 
          + theKVP.Value.ToString());

        if (theKVP.Value.BaseType != null)
        {
            Console.WriteLine("base class = " 
              + theKVP.Value.BaseType.ToString());
        }
        else if (theKVP.Key is IWhatEver)
        {
            Console.WriteLine("This is an IWhatEver interface");
            Console.WriteLine("This IWhatEver cast back to Button is : "
              + (theKVP.Key as Button).ToString() 
              + " : Name = " 
              + (theKVP.Key as Button).Name);
        }

        Console.WriteLine();
    }
}


这篇关于将接口作为参数传递-需要实型.的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆