【问题标题】:Storing the generic class T in a variable and reusing it in sub methode将泛型类 T 存储在变量中并在子方法中重用它
【发布时间】:2018-06-22 08:20:08
【问题描述】:

将泛型类 T 存储在变量中并在子方法中重用它。

对于一个在少数对象上有杂物的 WebService:

Foo:        Bar:        Etc..
SetFoo      SetBar      SetEtc
GetFoo      GetBar      GetEtc
UpdateFoo   UpdateBar   UpdateEtc
DeleteFoo   DeleteBar   DeleteEtc
GetList     ..          ..
GetPending  ..          ..
Processed   ..          ..

我在客户端有以下单例通用包装器,方法如下:

public bool Get<T>(int i, out DloExtention result)
// DloExtention is an interface implemented by foo, bar, etc..
{
    result = null;
    try
    {
        if (typeof(T) == typeof(Foo))
        {
            result = WebserviceClient.GetFoo(i);
        }
        else if (typeof(T) == typeof(Bar))
        {
            result = WebserviceClient.GetBar(i);
        }
        else if (typeof(T) == typeof(Etc))
        {
            result = WebserviceClient.GetEtc(i);
        }
        else
        {
            throw new NotSupportedException("Get<T>, T is not a supported type.");
        }
    }
    catch (Exception ex)
    {
        Log4N.Logger.Error($"Error in Namespace.ClientSide.Get<{nameof(T)}>(int {i} ). " + ex.Message);
        return false;
    }
    return true;
}

所以我可以用同一个通用对象简单地处理所有类型:

class Processor
{
    HashSet<int> validOperation = new HashSet<int>();
    HashSet<int> invalidOperation = new HashSet<int>();

    internal void Run<T>()
    {
        if (Wrapper.Instance.GetListPending<T>(out int[] newEntityList) && newEntityList.Any())
        {
            ProcessEntities<T>(newEntityList, false);
        }
    }

    private void ProcessEntities<T>(int[] idsEnt, bool singleMode)
    {
        foreach (var idEnt in idsEnt)
        {
            ProcessEntity<T>(idEnt, false);
        }

        CloseValidOperation();
        RemoveInvalidOperation();
    }

    internal void ProcessIncident<T>(int idEnt)
    {
        if (Wrapper.Instance.Get<T>(idEnt, out LanDataExchangeCore.LanDataExchangeWCF.DloExtention currentEntity))
        {
            if (currentEntity.isValid() && currentEntity.toLocalDB())
            {
                validOperation.Add(idEnt);
            }
            else
            {
                invalidOperation.Add(idEnt);
            }
        }
    }

只有Wrapper.Instance.Get&lt;T&gt;Wrapper.Instance.GetListPending&lt;T&gt; 需要泛型参数。 但是每个方法都需要使用它才能将&lt;T&gt; 传递给最后一个方法。

有没有办法将Run&lt;T&gt; 调用中的&lt;T&gt; 保存到私有变量中,以便类的内部方法可以使用它?

我尝试添加Type myType;,但找不到在通用调用中使用它的方法。 Wrapper.Instance.Get&lt;T&gt; 的示例

Type myType; // class property

var fooWrapperGet = typeof(Wrapper).GetMethod("Get");
var fooOfMyTypeMethod = fooWrapperGet.MakeGenericMethod(new[] { myType });
//fooOfMyTypeMethod.Invoke(Wrapper.Instance , new object[] { new myType() });

// fooWrapperGet, as my wrapper is a singleton, Wrapper dont exposed Get<T>, but Wrapper.instance will expose it. 
// new myType()  <- do not compile. 

【问题讨论】:

  • 如果你需要在不同的函数中使用相同的类型,为什么不让你的类通用(而不是你的方法)?
  • @Freggar,好吧,因为在我的脑海中,该类的同一个实例将针对不同的类型进行处理,例如 myObj.Run&lt;foo&gt;(); myObj.Run&lt;bar&gt;(); myObj.Run&lt;etc..&gt;();。但是,是的,我可以简单地做到这一点。
  • 我真的很讨厌星期五。 @Freggar,您选择如何获得满足:要么发布答案,要么您认为这是一个愚蠢无用的 x/y,我将其删除。
  • 我希望您在回答您的实际问题时接受@Enigmativity 的回答。我的建议将要求您几乎完全重构您的代码,所以我不认为答案会公正地解决这个问题。

标签: c#


【解决方案1】:

这对你有用吗?

private Dictionary<Type, Func<int, DloExtention>> gets =
    new Dictionary<System.Type, Func<int, DloExtention>>()
    {
        { typeof(Foo), WebserviceClient.GetFoo },
        { typeof(Bar), WebserviceClient.GetBar },
        { typeof(Etc), WebserviceClient.GetEtc },
    };

public bool Get<T>(int i, out DloExtention result)
{
    result = null;
    var flag = false;
    if (gets.ContainsKey(typeof(T)))
    {
        result = gets[typeof(T)](i);
        flag = true;
    }
    return flag;
}

这样做的好处是您可以在运行时填充字典。

【讨论】:

  • Ps 有趣的事实是,我在问题中的最后一个代码来自您的 answer
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-20
  • 2012-01-26
  • 1970-01-01
  • 2018-09-23
  • 2022-10-17
  • 1970-01-01
相关资源
最近更新 更多