【问题标题】:Refer to Self's Type inside a class在类中引用 Self 的 Type
【发布时间】:2015-05-11 12:00:19
【问题描述】:

在我的 C# 类中,我想引用类本身的类型,可以吗?

我的示例代码:

在一行

private static List<CRcpParmPropEle<CParam1, string>> ParmPropList;

我不想使用“CParam1”,我希望使用一些通用的方式(比如“this”)来引用自己。因为我有很多像 CParam1 这样的类,所以每个人都需要以这种方式引用自己。

class CParam1
{

    private double m_Prop1;

    private static List<CRcpParmPropEle<CParam1, string>> ParmPropList;

    public CParam1()
    {

    }

    ////-> I wish to replace Cparam1 to something like this
    public static List<CRcpParmPropEle<CParam1, string>> getParmPropList()
    {
        if (ParmPropList == null)
        {                
            ParmPropList.Add(new CRcpParmPropEle<CParam1, string>("Prop1", "BA", 0, false));
            //-> I wish to replace Cparam1 to something like this
        }
        return ParmPropList;
    }

    public string Prop1
    {
        get
        {
                return m_Prop1.ToString();
        }
        set
        {
            m_Prop1 = -1;
            double dW1;
            if (double.TryParse(value, out dW1))
            {
                    m_Prop1 = dW1;
            }
        }
    }

public class CRcpParmPropEle<T,TProp>
{
    public Func<T, TProp> getter;
    public Action<T, TProp> setter;

    public string PropName { get; set; }
    public string ColPos { get; set; }
    public int ColNum { get; set; }
    public int RowNum { get; set; }

    public bool ReadOnly { get; set; }

    public CRcpParmPropEle(string strPropName, string strColPos, int nRowNum, bool bReadOnly)
    {
        PropName = strPropName;
        ColPos = strColPos;
        RowNum = nRowNum;

        ReadOnly = bReadOnly;

        var prop = typeof(T).GetProperty(PropName);    //typeof(rcpObj).GetProperty(propName);
        getter = (Func<T,TProp>)Delegate.CreateDelegate(typeof(Func<T,TProp>), prop.GetGetMethod());
        setter = (Action<T,TProp>)Delegate.CreateDelegate(typeof(Action<T,TProp>), prop.GetSetMethod());            
    }
}

【问题讨论】:

  • 您是否尝试过使用this.GetType()
  • 是否可以选择让您的 CParam1 类型类派生自公共基类或实现公共接口?这将允许您让列表类型引用公共基础或接口,而不是类本身。另外,鉴于此列表已经是静态的,将其放在其他地方怎么样?
  • @slugster,类型名在类的静态属性的类型声明中。
  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • @DWright 是的,好点,但方法/字段通常是静态的,因为像 Resharper 这样的工具建议它而不是因为它们需要。 IOW 方法/字段是否需要是静态的,这种情况可以参考this

标签: c# types self


【解决方案1】:

一般来说,不会。没有办法做到这一点。由于在通常使用 this 的上下文中,无论如何都要编写特定于类型的代码,而且由于我们习惯于无论如何都必须为静态成员指定类型名称,所以这似乎不是什么困难。

但是,有几个替代方案可以在您的场景中使用,都涉及泛型。

第一个是将新对象的构造委托给通用辅助方法:

public static List<CRcpParmPropEle<CParam1, string>> getParmPropList()
{
    if (ParmPropList == null)
    {
        AddToList(ParmPropList, "Prop1", "BA", 0, false);
    }
    return ParmPropList;
}

private static void AddToList<T>(List<CRcpParmPropEle<T, string>> list, string s1, string s2, int i, bool f)
{
    list.Add(new CRcpParmPropEle<T, string>(s1, s2, i, f));
}

这样,实际类型是从传入的List&lt;T&gt;对象的类型推断出来的,所以不需要重述。当然,您不会在somewhere 中指定类型。它只是不会在这个特定的呼叫站点结束。

另一种选择是使用静态帮助类来实现 CParam1 类的静态功能:

static class ParmPropClass<T>
{
    private static List<CRcpParmPropEle<T, string>> ParmPropList;

    public static List<CRcpParmPropEle<T, string>> getParmPropList()
    {
        if (ParmPropList == null)
        {
            ParmPropList.Add(new CRcpParmPropEle<T, string>("Prop1", "BA", 0, false));
        }
        return ParmPropList;
    }
}

然后,当您使用静态成员时,您必须将类型名称指定为ParmPropClass&lt;CParam1&gt;(或其他任何名称,具体取决于您最终命名的帮助类)。同样,您不必在某处指定类型名称,但调用站点不需要。

事实上,如果您在多个位置完全使用这种模式,则通用帮助器类型可能是更好的选择,因为那时您不必复制/一直粘贴代码(无法在所有复制到的地方修复一些错误的秘诀)。

【讨论】:

    【解决方案2】:

    这里没有直截了当或易于实施的答案。我会给你三个选项,但我认为其中任何一个都不会比更改所有课程更容易。如果我必须这样做,我会使用依赖注入器。从长远来看,您会过得更好,下次您将能够更轻松地处理这些事情。如果我必须快速而绝望地做这件事,我会使用反射。

    选项 1 - 反射

    您可以在运行时使用反射来组装列表。 查看这篇文章,了解在运行时使用反射创建列表的示例。 Generic list by using reflection

    这会让你的代码很难维护,你必须在整个过程中使用反射来管理列表。您可能会在运行时错误和调试困难中增加更多的麻烦,而不是到处更改它

    选项 2 - 通用基类

    如果您可以从公共基类 CPARAMBASE 中实现所有 CPARAM1 类型对象,则可以使用公共基类定义列表。

    private static List<CRcpParmPropEle<CParamBase, string>> ParmPropList;
    

    选项 3 - 依赖注入

    这不是您可以在 SO 答案中涵盖的内容,而是查看依赖注入。

    您在所有 CPARAM 类型类之间创建一个接口,然后根据注入的类型注入具体类型。

       [Inject]
       private static List<CRcpParmPropEle<ICParam, string>> ParmPropList;
    

    在您的依赖注入中,您可以定义 ICParam 实例。

    this.Bind<List<CRcpParmPropEle<ICParam, string>>>()
        .To<List<CRcpParmPropEle<CParam1, string>>>()
        .WhenInjectedInto(typeof(CParam1));
    

    查找 Ninject,然后查找上下文绑定和 http://www.ninject.org/wiki.html

    【讨论】:

      猜你喜欢
      • 2015-03-03
      • 1970-01-01
      • 2021-06-05
      • 2018-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多