C# 如何获取类型的默认泛型委托

C# 如何获取类型的默认泛型委托,c#,generics,C#,Generics,我有这样一个普通委托: public delegate T SomeHandler<T>(T input); public class SomeClass<T> { private SomeHandler<T> m_handler; public SomeClass(SomeHandler<T> handler) { m_handler = handler; } public void DoSomeStuff(T

我有这样一个普通委托:

public delegate T SomeHandler<T>(T input);
public class SomeClass<T>
{
  private SomeHandler<T> m_handler;

  public SomeClass(SomeHandler<T> handler)
  {
    m_handler = handler;
  }

  public void DoSomeStuff(T input)
  {
     T result = m_handler(input);
     // some stuff
  }
}
在某些情况下,使用特定于其实现的特殊处理程序实例化该类型:

public class Example
{
  private SomeClass<string> m_typicalCase;

  private SomeClass<string> m_specialCase;

  public Example()
  {
    m_typicalCase = new SomeClass<string>(DefaultHandlers.DefaultStringHandler);
    m_specialCase = new SomeClass<string>(SpecialHandler);
  }

  private string SpecialHandler(string input)
  {
    string result;
    // Do something special
    return result;
  }
}
公共类示例
{
私人某类m_-typicalCase;
私人某类m_特殊课程;
公共示例()
{
m_typicalCase=新的SomeClass(DefaultHandlers.DefaultStringHandler);
m_specialCase=新的SomeClass(SpecialHandler);
}
专用字符串特殊句柄(字符串输入)
{
字符串结果;
//做点特别的事
返回结果;
}
}
我想为SomeClass创建一个默认构造函数,该构造函数总是使用该类型的相同默认处理程序实例化该类,但由于在编译时不知道该类型,因此无法返回正确类型的委托

public class SomeClass<T>
{

  ...

  public SomeClass()
  {
    m_handler = DefaultHandlers.GetDefaultHandler<T>();
  }

  ...

}
公共类SomeClass
{
...
公共类()
{
m_handler=DefaultHandlers.GetDefaultHandler();
}
...
}
像这样

public static class DefaultHandlers
{
  public static SomeHandler<T> GetDefaultHandler<T>()
  {
    if (typeof(T) == typeof(string))
    {
      return DefaultStringHandler;
    }
  }
}
公共静态类DefaultHandler
{
公共静态SomeHandler GetDefaultHandler()
{
if(typeof(T)=typeof(string))
{
返回DefaultStringHandler;
}
}
}
这不起作用,因为DefaultStringHandler返回一个字符串,而方法需要T

我发现实现这一点的唯一方法是生成SomeClass的特定于类型的子类,该子类重载默认构造函数:

public class SomeStringClass : SomeClass<string>
{

  public SomeStringClass()
  : base(DefaultHandlers.DefaultStringHandler)
  {
  }

  public SomeStringClass(SomeHandler<string> handler)
  : base(handler)
  {
  }

}
公共类SomeStringClass:SomeClass
{
公共类()
:base(DefaultHandlers.DefaultStringHandler)
{
}
公共SomeStringClass(SomeHandler处理程序)
:base(处理器)
{
}
}
如果泛型类型在实例化特定类型的类时可以使用特定于类型的重载构造函数,那将非常有趣:

public class Foo<T>
{
  public Foo<string>(string input)
  {
  }

  public Foo<int>(int input)
  {
  }

  public Foo(T input)
  {
  }
}
公共类Foo
{
公共Foo(字符串输入)
{
}
公共Foo(int输入)
{
}
公共Foo(T输入)
{
}
}

必须有一种更优雅的设计模式,也许是策略?

基于Jon Skeet和Alexei Levenkov的评论。据我所知,像这样的事情可能就是你想要的

public delegate T SomeHandler<T>(T input);

public class SomeClass<T>
{
    private SomeHandler<T> m_handler;

    public SomeClass()
    {
        m_handler = (T input) => input;
    }

    public SomeClass(SomeHandler<T> handler)
    {
        m_handler = handler;
    }

    public void DoSomeStuff(T input)
    {
        T result = m_handler(input);
        // some stuff
    }
}
公共委托T SomeHandler(T输入);
公共类
{
私人萨穆汉德尔;
公共类()
{
m_handler=(T输入)=>输入;
}
公共SomeClass(SomeHandler)
{
m_handler=handler;
}
公共无效DoSomeStuff(T输入)
{
T结果=m_处理程序(输入);
//一些东西
}
}
另一种方法是将特定于字符串的行为移动到一个单独的类中,如果希望特定行为绑定到特定类型,只需创建该类的实例

public delegate T SomeHandler<T>(T input);

public class SomeClass<T>
{
    protected SomeHandler<T> m_handler;

    protected SomeClass()
    {

    }

    public SomeClass(SomeHandler<T> handler)
    {
        m_handler = handler;
    }

    public void DoSomeStuff(T input)
    {
        T result = m_handler(input);
        // some stuff
    }
}

public class SomeStringClass : SomeClass<string>
{
    public SomeStringClass()
    {
        m_handler = DefaultStringHandler;
    }

    private string DefaultStringHandler(string input)
    {
        // Do default string stuff here...
        return input;
    }

    public SomeStringClass(SomeHandler<string> handler):base(handler)
    {

    }
}
公共委托T SomeHandler(T输入);
公共类
{
受保护的SomeHandler m_handler;
受保护的类()
{
}
公共SomeClass(SomeHandler)
{
m_handler=handler;
}
公共无效DoSomeStuff(T输入)
{
T结果=m_处理程序(输入);
//一些东西
}
}
公共类SomeStringClass:SomeClass
{
公共类()
{
m_handler=DefaultStringHandler;
}
私有字符串DefaultStringHandler(字符串输入)
{
//在这里做默认字符串。。。
返回输入;
}
公共SomeStringClass(SomeHandler处理程序):基(处理程序)
{
}
}

您可以利用
动态
来获取类似
SomeClass()的内容


那么,对于其他类型,您希望默认处理程序做什么?如果总是“返回输入值”,那么这很简单。
(SomeHandler)DefaultStringHandler
应该可以工作。。。(也正如Jon Skeet指出的,如果它总是标识,那么您可以简单地使用lambda将其内联,例如:
x=>x
)我认为我的处理程序示例不太现实,它接受输入并返回相同的类型。实际上,有许多处理程序要么将类型T作为输入并输出其他内容,要么将其他类型T作为输出内容。有点像类型转换器。我希望默认行为根据T的类型而有所不同。
public delegate T SomeHandler<T>(T input);

public class SomeClass<T>
{
    protected SomeHandler<T> m_handler;

    protected SomeClass()
    {

    }

    public SomeClass(SomeHandler<T> handler)
    {
        m_handler = handler;
    }

    public void DoSomeStuff(T input)
    {
        T result = m_handler(input);
        // some stuff
    }
}

public class SomeStringClass : SomeClass<string>
{
    public SomeStringClass()
    {
        m_handler = DefaultStringHandler;
    }

    private string DefaultStringHandler(string input)
    {
        // Do default string stuff here...
        return input;
    }

    public SomeStringClass(SomeHandler<string> handler):base(handler)
    {

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Zoltan
{

    public class SomeClass<T>
    {
        private static readonly Func<T,T> FALL_BACK_HANDLER = a => a; //or what have you

        private readonly Func<T,T> m_handler;

        public SomeClass(Func<T,T> handler)
        {
            m_handler = handler;
        }

        public SomeClass()
        {
            m_handler = DefaultHandler.For<T>() ?? FALL_BACK_HANDLER;
        }

        public void DoSomeStuff(T input)
        {
            T result = m_handler(input);
            Console.WriteLine(result);
        }
    }

    public static class DefaultHandler
    {
        public static Func<T,T> For<T>()
        {
            return TypeAware<T>.Default;
        }

        private static class TypeAware<T>
        {
            private static readonly Func<T,T> DEFAULT;
            static TypeAware()
            {
                var type = typeof(T);
                if (type == typeof(string))
                {
                    DEFAULT = a => DefaultHandler.StringHandler((dynamic) a);
                }
                else if (type == typeof(int))
                {
                    DEFAULT = a => DefaultHandler.IntHandler((dynamic) a);
                }
                else
                {
                    DEFAULT = null;
                }
            }

            public static Func<T,T> Default { get { return DEFAULT; } }
        }

        public static string StringHandler(string a)
        {
            return a + " The default handler does some stuff!";
        }

        public static int IntHandler(int a)
        {
            return a + 2;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Zoltan
{    
    public class Program
    {
        public static void Main(string[] args)
        {
            var someStringObj = new SomeClass<string>();
            someStringObj.DoSomeStuff("Hello World.");//prints "Hello World. The default handler does some stuff!"

            var someIntObj = new SomeClass<int>();
            someIntObj.DoSomeStuff(1);//prints 3

            var someCustomDoubleObj = new SomeClass<double>(d => d - 2);
            someCustomDoubleObj.DoSomeStuff(3);//prints 1

            Console.Read();
        }
    }
}