如何在c#中获取泛型方法的值

时间:2017-01-12 19:59:24

标签: c# generics

我有这种通用方法:

public Guid Save<T>(T obj)
    {
        Guid newId = Guid.NewGuid();
        try
        {
            foreach (MethodInfo method in (typeof(T)).GetMethods())
            {
                if (IsXmlElement(method))
                {
                    // A way to get this method's value
                    // e.g. if T has method GetName, and GetName was assigned 'John' 
                    //i.e. object.GetName = 'John'Is there a way to get 'John' from this GetName method?
                }
            }

然后,我有一个对象,myObject.Name = 'John' ...并且myObject被传递给save方法因此:Save(myObject);有没有什么方法可以在Save方法中获得值'John'? / p>

任何建议都将不胜感激。感谢。

5 个答案:

答案 0 :(得分:2)

如果你想根据泛型类型迭代属性(我假设你的意思是你的例子中的“方法”),你可以使用TypeDescriptor类:

public Guid Save<T>(T obj)
{
    Guid newId = Guid.NewGuid();
    try
    {
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(typeof(T)))
        {
            if (IsXmlElement(method))
            {
                object value = property.GetValue(obj);
                // ...
            }
        }

如果您总是推断类型(即T始终是obj的类型而不是基本类型或界面),则根本不需要泛型:

public Guid Save(object obj)
{
    Guid newId = Guid.NewGuid();
    try
    {
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(obj))
        {
            if (IsXmlElement(method))
            {
                object value = property.GetValue(obj);
                // ...
            }
        }

您可能还想查看XmlSerializer课程。您似乎手动从源对象创建XML。 XmlSerializer可能已经拥有了你需要的所有工作。

答案 1 :(得分:1)

如果可能的话,我会强制要求传递给您的泛型方法的任何类型都是从公共接口派生的。然后,您可以引用该接口中定义的任何属性(在本例中为name)。您的方法定义如下所示:

 public Guid Save<T>(T obj) where T : iSaveable
 { 
    ...

其中iSaveable将是您创建的界面的名称。

答案 2 :(得分:1)

听起来你真的想要使用属性而不是本例中的方法。在属性的情况下,你会写这样的东西:

void Main()
{
    var obj = new TestObject();
    foreach (var prop in obj.GetType().GetProperties())
    {
        Console.WriteLine("{0} = '{1}'", prop.Name, prop.GetValue(obj));
    }
}

class TestObject
{
    public TestObject()
    {
        FirstName = "John";
        LastName = "Hancock";
    }

    public string FirstName { get; }
    public string LastName { get; }
}

您还可以通过将GetProperties调用更改为GetFields来使用此值来获取字段值而不是属性。这只适用于公共字段或属性。如果您想要保存非公开字段或属性,则需要将BindingFlags添加到GetProperties / GetFields来电:

void Main()
{
    var obj = new TestObject();
    foreach (var prop in obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic))
    {
        Console.WriteLine("{0} = '{1}'", prop.Name, prop.GetValue(obj));
    }
}

class TestObject
{
    private readonly string _firstName;
    private readonly string _lastName;

    public TestObject()
    {
        _firstName = "John";
        _lastName = "Hancock";
    }
}

答案 3 :(得分:0)

您可以将对象强制转换为已知类型,然后访问Name属性。由于您没有向我们展示您的课程,因此我们假装您的对象属于Person类型,然后是Save内部:

if (obj is Person)
{
    string name = ((Person)obj).Name;
} 
else
{ ... }

有关is here的更多信息。

答案 4 :(得分:0)

如果您对类型参数设置约束,则可以这样:

public Guid Save<T>(T obj) where T : ISomeInterface
    {
        Guid newId = Guid.NewGuid();
        try
        {
            foreach (MethodInfo method in (typeof(T)).GetMethods())
            {
                if (IsXmlElement(method))
                {
                    // A way to get this method's value
                    // e.g. if T has method GetName, and GetName was assigned 'John' 
                    //i.e. object.GetName = 'John'Is there a way to get 'John' from this GetName method?
                }
            }

以及myObject实现ISomeInterface接口的位置。

希望有所帮助