假设您正在创建一组对象来处理某些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);
}
任何想法或指导?
答案 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元素名称和值。写一次,到处使用!