1

データベースの設定に基づいてフィールドの可視性を制御するdataannotations属性を作成しようとしています。この属性は、複数のクライアントによって使用されるシステム内で使用されます。さらに、フィールドの可視性はその場で変更できる必要があります。ビューの各フィールドの周りにifステートメントを実行できることはわかっていますが、それを回避し、次のようにビューモデル内の可視性コントロールを維持しようとしています。

[Visible(FirstName)]
public string FirstName { get; set; }

ResourceType(T4を使用して生成され、データベースにアクセスするために必要なコードが含まれている)というリソースクラスのメソッドから値を取得するこのカスタム属性を作成してみました。

public class VisibleAttribute : Attribute, IMetadataAware
{
    /// <summary>
    /// Whether this field is visible
    /// </summary>
    public bool Hidden { get; set; }

    public VisibleAttribute(string theFieldName)
    {
        ResourceType resources = new ResourceType();
        Type _resourceType = typeof(ResourceType);

        MethodInfo getHidden = _resourceType.GetMethod("IsHidden");
        object[] requiredParams = new object[] { theFieldName };
        Hidden = (bool)getHidden.Invoke(resources, requiredParams);
    }


    public void OnMetadataCreated(ModelMetadata metadata)
    {
        metadata.ShowForEdit = !Hidden;
        metadata.HideSurroundingHtml = Hidden;
    }
}

ResourceTypeクラスの抜粋を次に示します。

public class ResourceType
{

public const string Creditors_SecondaryCreditorsPayOffYesNo_Require = "Prop_Creditors_SecondaryCreditorsPayOffYesNo_Require";
    public static string Prop_FieldName_Require 
    { 
        get { return GetHiddenOption(FieldName) ? "true" : "false"; } 
    }

internal static bool GetHiddenOption(string fieldName)
{
    < < Logic here to get the option from the database > >
}

同じ属性を試しましたが、次のコンストラクターを使用しました。

public VisibleAttribute(string theFieldName)
    {
        ResourceType resources = new ResourceType();
        Type _resourceType = typeof(ResourceType);

        PropertyInfo getHidden = _resourceType.GetProperty(theFieldName);
        Hidden = (bool)getHidden.GetValue
    }

これらの2つの試行で発生する問題は、コードがコンストラクター内にあるため、IISのリセット後にページを最初にロードしたときにのみ実行されることです。そのため、可視性の設定に加えた変更は、IISを再度リセットしないと反映されません。

また、ページリクエストごとに1回だけ設定をロードしようとするカスタムDataAnnotationsModelMetadataProviderを作成してみました。

public class EGTDataAnnotationsModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, 
        Func<object> modelAccessor, Type modelType, string propertyName)
    {
        var data = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
        var visibleAttributeMetadata = attributes.SingleOrDefault(a => typeof(VisibleAttribute) == a.GetType());

        if (visibleAttributeMetadata != null)
        {
            VisibleAttribute visibleAttribte = (VisibleAttribute)visibleAttributeMetadata;

            if (!visibleAttribte.VisibleIsSet)
            {
                PropertyInfo getHidden = visibleAttribte.ResourceType.GetProperty("Prop_" + WebUtils.RemoveSectionNameSpace(visibleAttribte.SectionName) + "_" + visibleAttribte.FieldName + "_Hide");
                visibleAttribte.IsHidden = bool.Parse(getHidden.GetValue(null, null).ToString());

                data.HideSurroundingHtml = visibleAttribte.IsHidden;
                data.ShowForEdit = !visibleAttribte.IsHidden;

                visibleAttribte.VisibleIsSet = true;
            }
            else
            {
                data.HideSurroundingHtml = visibleAttribte.IsHidden;
                data.ShowForEdit = !visibleAttribte.IsHidden;
            }
        }

        return data;
    }
}

ModelMetadataProviderに関する問題の1つは、CreateMetadataメソッドが1つのリクエスト中に1つのフィールドに対して何度も実行されることです。リクエストごとにデータベースを5〜10回以上呼び出して、リクエストの開始以降変更されていない設定を取得することは、非常に非効率的なコードであり、パフォーマンスが大幅に低下します。すでに設定をロードしたことを示すフラグを設定しようとすると、IISがリセットされるまで設定の変更が表示されない、上記と同じシナリオに戻ります。

データベースの変更をリアルタイムで確認するために使用できる方法について、誰かが私にいくつかの指針を教えてくれることを願っています。それとも私は不可能なことをしようとしていますか?前もって感謝します。

4

1 に答える 1

0

メタデータプロバイダーのアプローチを、その単一のリクエストだけで値をキャッシュすることと組み合わせることができます。このために、現在のHttpContextでItemsディクショナリを使用できます。リダイレクトによってアイテムがクリアされるため、これには注意してください。

string cacheKey = String.Format("IsVisible-{0}", propertyName)
if(!HttpContext.Current.Items.Contains(cacheKey))
    HttpContext.Current.Items[cacheKey] = //get setting from db

bool isVisible = (bool)HttpContext.Current.Items[cacheKey];

現在の要求だけでなく値をキャッシュしたい場合は、 ASP .Net Cacheの使用を検討することもできます(メタデータプロバイダー内で、要求ごとに1回設定を読み込もうとしていると述べましたが)

于 2012-12-06T22:51:49.913 に答える