使用泛型时,转换为抽象类或接口

时间:2009-01-21 02:09:33

标签: c# reflection casting abstract-class generics

我有这个方法Verify_X,在数据绑定期间为列表框选择的值调用。问题是强类型数据源。我想使用抽象类BaseDataSource或接口来调用支持的方法: 参数[]和Select(),而不是使用如下所示的最具体的实现。

这样就可以将一种方法用于我拥有的所有不同类型的数据源,而不是每种方法都有一个方法。他们都以同样的方式继承。

这是继承/实现链

public class DseDataSource : ProviderDataSource<SCCS.BLL.Dse, DseKey>

public abstract class ProviderDataSource<Entity, EntityKey> : BaseDataSource<Entity, EntityKey>, ILinkedDataSource, IListDataSource
    where Entity : SCCS.BLL.IEntityId<EntityKey>, new()
    where EntityKey : SCCS.BLL.IEntityKey, new()

public abstract class BaseDataSource<Entity, EntityKey> : DataSourceControl, IListDataSource, IDataSourceEvents
    where Entity : new()
    where EntityKey : new()

BaseDataSource具有我需要的方法和属性。 DseDataSource通过以下方式实现:

public class DseDataSource : ProviderDataSource<SCCS.BLL.Dse, DseKey>

我知道可以编辑DseDataSource类,添加一个接口来访问Parameters []和Select(),然后编程,这允许我想要的,但这需要编辑NetTiers库,我很好奇看看是否可以这样做,因为它似乎很难。

    public static string Verify_DSE(string valueToBind, DseDataSource dataSource)
    {
        if (ListContainsValue(dataSource.GetEntityList(), valueToBind)) return valueToBind;
        CustomParameter p = dataSource.Parameters["WhereClause"] as CustomParameter;
        if (p != null)
        {
            p.Value = "IsActive=true OR Id=" + valueToBind;
            dataSource.Select();
            return valueToBind;
        }
        return string.Empty;
    }

    private static bool ListContainsValue(IEnumerable list, string value)
    {
        if (value.Length == 0) return true;

        foreach (object o in list)
        {
            IEntity entity = o as IEntity;
            if (entity != null)
            {
                if (entity.Id.ToString() == value)
                    return true;
            }
        }
        return false;
    }

最终结果将是代码,例如:

public static string Verify(string valueToBind, object dataSource)
{
//what is the correct way to convert from object
BaseDataSource baseInstance = dataSource as BaseDataSource;

if baseInstance != null)
{
    if (ListContainsValue(baseInstance.GetEntityList(), valueToBind)) return valueToBind;
    CustomParameter p = baseInstance.Parameters["WhereClause"] as CustomParameter;
    if (p != null)
    {
        p.Value = "IsActive=true OR Id=" + valueToBind;
        baseInstance.Select();
        return valueToBind;
    }
}

return string.Empty;
}

3 个答案:

答案 0 :(得分:2)

如果您无法更改类定义或使用某种扩展方法,则可以使用Reflection。以下是我使用关于代码的假设进行处理的示例:

    public static string Verify(string valueToBind, object dataSource)
    {
        ////what is the correct way to convert from object
        //BaseDataSource baseInstance = dataSource as BaseDataSource;
        Type type = dataSource.GetType();
        MethodInfo select = type.GetMethod("Select");
        PropertyInfo parameters = type.GetProperty("Parameters");
        PropertyInfo parameterGetter = null;
        object parametersInstance = null;
        if (parameters != null)
        {
            parametersInstance = parameters.GetValue(dataSource, null);
            type = parametersInstance.GetType();
            parameterGetter = type.GetProperty("Item");
        }

        //if baseInstance != null)
        if (select != null && parameters != null && parameterGetter != null)
        {
                if (ListContainsValue(baseInstance.GetEntityList(), valueToBind)) return valueToBind;
                CustomParameter p = parameterGetter.GetValue(parametersInstance, new object[] {"WhereClause" }) as CustomParameter;

                if (p != null)
                {
                        p.Value = "IsActive=true OR Id=" + valueToBind;
                        select.Invoke(dataSource, null);
                        return valueToBind;
                }
        }

        return string.Empty;
    }

答案 1 :(得分:1)

谢谢John,你真的把我放在了正确的道路上。 我最终得到了以下代码:

    public string Verify(string valueToBind, object dataSource)
    {
        IListDataSource listDataSource = dataSource as IListDataSource;
        if (listDataSource != null)
        {
            if (ListContainsValue(listDataSource.GetEntityList(), valueToBind)) return valueToBind;
        }

        Type type = dataSource.GetType();
        MethodInfo select = type.GetMethod("Select", new Type[0]);
        PropertyInfo parameterCollectionInfo = type.GetProperty("Parameters");
        ParameterCollection pc = parameterCollectionInfo.GetValue(dataSource, null) as ParameterCollection;

        if (pc != null)
        {
            CustomParameter p = pc["WhereClause"] as CustomParameter;
            if (p != null)
            {
                p.Value = "IsActive=true OR Id=" + valueToBind;
                select.Invoke(dataSource, null);
                return valueToBind;
            }
        }

        return string.Empty;
    }

答案 2 :(得分:0)

因为代码“按原样”不可用,所以很难讨论实际问题......你能否将示例简化为不依赖于外部库/类的东西?

我可以确认:NetTiers是否生成了DseDataSource?在哪种情况下,NetTiers会生成“部分”类吗?如果是这样,您可以在第二个类文件中添加interface-implementation:

namespace YourNamespace {
    partial class DseDataSource : IYourInterface {
        // implement interface
    }
}

这为DseDataSource类添加了功能,而无需编辑生成的代码。