2

リストボックスで選択された値のデータバインド中に呼び出されるこのメソッドVerify_Xがあります。問題は、厳密に型指定されたデータソースです。以下に示すように、最も具体的な実装を使用する代わりに、抽象クラス BaseDataSource またはインターフェイスを使用して、サポートされているメソッドを呼び出したい: Parameters[] および Select()。

これは、それぞれにメソッドを用意する代わりに、私が持っているさまざまなタイプのデータソースすべてに 1 つのメソッドを使用できるようにするためです。それらはすべて同じ方法で継承されます。

継承・実装の連鎖はこちら

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() にアクセスするためのインターフェイスを追加してから、それに対してプログラムすることが可能であることはわかっています。とても難しそうだったのでできます。

    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

クラス定義を変更したり、ある種の拡張メソッドを使用したりできない場合は、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;
    }
于 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

コードは「そのまま」では使用できないため、実際の問題について議論するのは非常に困難です...例を外部ライブラリ/クラスに依存しないものに単純化できますか?

確認できますか: はDseDataSourceNetTiers から生成されていますか? どの場合、NetTiers は「部分的な」クラスを生成しますか? その場合、2 番目のクラス ファイルにインターフェイスの実装を追加できます。

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

DseDataSourceこれにより、生成されたコードを編集する必要なく、クラスに機能が追加されます。

于 2009-01-21T02:25:47.547 に答える