2

我有这个方法 Verify_X,它在数据绑定期间为列表框选定值调用。问题是强类型数据源。我想使用抽象类 BaseDataSource 或接口来调用支持的方法:Parameters[] 和 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;
}
4

3 回答 3

2

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

    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;
    }
于 2009-01-21T04:58:19.157 回答
1

谢谢约翰,你真的让我走上了正确的道路。我最终得到以下代码:

    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;
    }
于 2009-01-21T06:57:09.400 回答
0

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

我可以确认:是DseDataSource从 NetTiers 生成的吗?在这种情况下,NetTiers 会生成“部分”类吗?如果是这样,您可以在第二个类文件中添加接口实现:

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

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

于 2009-01-21T02:25:47.547 回答