从未知接口获取属性

时间:2018-11-05 09:05:19

标签: c# .net oop interface ienumerable

我有两个接口IndexFieldBatchField他们没有共享相同的基类。它们都具有Name属性。所以给定这种方法

private void Initialize(IEnumerable fields)
{
    List<string> fieldNames = new List<string>();

    foreach (object fld in fields)
    {
        string name = string.Empty;

        if (fld is IndexField indexField)
        {
            name = indexField.Name;
        }
        else if (fld is BatchField batchField)
        {
            name = batchField.Name;
        }

        fieldNames.Add(name);
    }

    // Do something ...
}

我传入了batchfieldsindexfields的集合作为参数。我想将name属性分配给新的字符串列表。

我知道我可以通过List<string> fieldNames作为方法参数,但是我的问题是:

尽管我不知道正确的接口类型,有没有办法避免if语句并调用Name属性?

我从这段代码开始,认为这是一个很好的代码,但也许有些类似

List<string> fieldNames = new List<string>();

foreach (object fld in fields)
{
    fieldNames.Add(fld.Name); // fld might be an IndexField or BatchField interface
}

4 个答案:

答案 0 :(得分:4)

通过反射获取属性

private object GetPropertyValue(object item, string property)
{
    // No value
    object value = null;

    var pi = item.GetType().GetProperty(property);

    // If we have a valid property, get the value
    if (pi != null)
        value = pi.GetValue(item, null);

    // Done
    return value;
}

这是实现方法:

private void Initialize(IEnumerable fields)
{
    List<string> fieldNames = new List<string>();

    foreach (object fld in fields)
    {
        string name = GetPropertyValue(fld, "Name").ToString();
        fieldNames.Add(name);
    }

    // Do something ...
}

我无法测试您的代码,因此您可能需要对其进行调整。

在此处使用反射可能是不好的做法。您可能应该修复接口或为方法创建重载。

答案 1 :(得分:4)

另一个使用linq的衬板:

fieldNames.AddRange(
     fields.Select(obj => (obj as IndexField)?.Name ?? (obj as BatchField)?.Name));

See a live demo on .Net fiddle.

尽管理想情况下,您应该更改IndexFieldBatchField以实现我在问题注释中所写的通用接口。

答案 2 :(得分:1)

简单地使用

SitemapSpider

答案 3 :(得分:1)

在最后一个foreach语句中,您无法访问Name属性,因为fld是对象类型。您可以创建另一个interface并从中继承两个interfaces,然后将上一个fld中的foreach类型从object更改为新创建的接口。像这样:

public interface IBaseInterface
{
    String Name { get; set; }
}

public interface IndexField: IBaseInterface
{        
}

public interface BatchField: IBaseInterface
{
}

然后:

foreach (BaseInterface fld in fields)
{
    fieldNames.Add(fld.Name); 
}

或更简单的使用LINQ:

List<string> fieldNames = (from IBaseInterface fld in fields select fld.Name).ToList();