关于C#中泛型的方法问题

时间:2009-12-03 22:16:56

标签: c# generics

假设您正在创建一组对象来处理某些XML解析,并且所有这些对象都采用完全相同的对象,XElement ......就这样

public class User
{
    public User(XElement xmlElement)
    {
          Id = xmlElement.GetElementValue("UserId"); 
    }

    public string Id { get; set; }
}

我想做的是一种像这样的方法..

public static T ToParsedObject<T>(this XElement xmlElement) where T : new()
{
    return new T(xmlElement);
}

我认为不可能像这样做一个静态(扩展方法),但我想把它作为一个我可以重用的方法。我已经厌倦了写作...... ...

public static User ToUser(this XElement xmlElement)
{
    return new User(xmlElement);
}

任何想法或指导?

4 个答案:

答案 0 :(得分:7)

不幸的是,没有办法像这样提供构造函数调用。

两个可能的选择:

  • 使类型为mutable(ick)并使其实现一个接口,例如: IParseableFromXElement。然后你可以写:

    public static T ToParsedObject<T>(this XElement xmlElement) 
        where T : new(), IParseableFromXElement
    {
        T ret = new T();
        ret.Parse(xmlElement);
        return ret;
    }
    
  • 从类型到委托构建类型的字典:

    static Dictionary<Type, Func<XElement, object>> factories = 
        new Dictionary<Type, Func<XElement, object>> 
    {
        { typeof(User), x => new User(x) },
        ...
    };
    
    public static T ToParsedObject<T>(this XElement xmlElement) 
    {
        Func<XElement, object> factory = factories[typeof(T)];
        return (T) factory(xmlElement);
    }
    

两者都有点hacky,但他们会工作......

答案 1 :(得分:3)

你可以用反射来解决这个问题:

public static class XElementExtensions
{
    public static T To<T>(this XElement el)
    {
        //var ctor = typeof(T).GetConstructor(new[] { typeof(XElement) });
        //if (ctor == null) /* do something */

        return (T)Activator.CreateInstance(typeof(T), new[] { el });
    }
}

您不需要构造函数检查,但如果您想采取特殊操作,例如返回default(T),则有必要。

您可以像这样使用此方法:

User u = xmlElement.To<User>();

我确实想知道,这样做的好处就是简单地调用对象上的构造函数:

User u = new User(xmlElement);

哎呀,这个角色少了一个! :)

答案 2 :(得分:1)

反思怎么样?

public static T ToParsedObject<T>(this XElement xmlElement) 
    where T : new()
{
    return (T) Activator.CreateInstance(typeof(T), xmlElement);
}

答案 3 :(得分:0)

正如马特指出的那样,这并没有真正为你节省打字。您仍然需要在类中编写转换代码。但也许对你的问题存在一些误解。是不是你真的想要删除构造函数并为XElement创建一个方法扩展,每次再使用相同的语法?像这样的东西?

/// <summary>
/// Try to parse an XElement into a matching type. Type must have an Id
/// </summary>
/// <returns>newly created type with Id and other properties filled</returns>
public static T ToParsedObject<T>(this XElement xmlElement)
    where T : new()
{
    T item = new T();
    Type type = typeof(T);

    // you can use GetProperties to go through all of them dynamically
    PropertyInfo prop = type.GetProperty("Id");
    prop.SetValue(item, xmlElement.Element(
        XName.Get(type.Name + "Id")),         // creates UserId or CustomerId etc
        null);
    return item;
}

根据您对XML元素的正确命名的依赖程度,您可以使用此方法来消除创建单个类型转换代码的负担。您甚至可以遍历每个属性,并动态地找到匹配的XML元素名称和值。写一次,到处使用!