0

私は2つのクラスを持っています:

public class CustomerViewModel {
  public SystemViewModel system { get;set; }
}

public class SystemViewModel {
  public bool isReadOnly { get; set; }
}

メソッド コントローラー アクションには、コードを実行し、ユーザーが読み取り専用または書き込みアクセス権を持っているかどうかを判断するカスタム フィルター属性があります。この属性は、複数のコントローラーにわたる複数のアクションに適用できます。

これまでのところ、リフレクションを使用して、次を使用してモデルにアクセスできます。

var viewModel = filterContext.Controller.ViewData.Model;

別のアクションでは SalaryViewModel のようなものになる可能性があるため、このモデルを CustomerViewModel にキャストすることはできません。私が知っていることは、読み取り専用プロパティを必要とするモデルには SystemViewModel プロパティがあるということです。

カスタム フィルターから、読み取り専用の値を変更できるようにする方法が必要です。

これまでのところ、私はこれを持っています:

public override void OnActionExecuted(ActionExecutedContext filterContext) {
    var viewModel = filterContext.Controller.ViewData.Model;

    var systemViewModelPropertyInfo = model.GetType()
        .GetProperties()
        .FirstOrDefault(p => p.PropertyType == typeof(SystemViewModel));

    if (systemViewModelPropertyInfo != null) {
        // Up to here, everything works, systemViewModelPropertyInfo is of
        // type PropertyInfo, and the systemViewModelPropertyInfo.PropertyType 
        // shows the SystemViewModel type
        // If we get here, the model has the system property
        // Here I need to try and set the IsReadOnly property to true/false;
        // This is where I need help please
    }
}

解決済み これを解決するために協力してくれたすべての人に感謝します。私が探していたソリューションを提供してくれたJulián Urbanoに感謝します。フィルター内からの結果のコードは次のとおりです。

public override void OnActionExecuted(ActionExecutedContext filterContext)
{
    try
    {
        var viewModel = filterContext.Controller.ViewData.Model;
        var systemViewModelPropertyInfoCount = viewModel.GetType().GetProperties().Count(p => p.PropertyType == typeof(SystemViewModel));

        if(systemViewModelPropertyInfoCount == 1)
        {
            var systemViewModelPropertyInfo = viewModel.GetType().GetProperties().First(p => p.PropertyType == typeof(SystemViewModel));
            if(systemViewModelPropertyInfo != null)
            {
                var systemViewModel = systemViewModelPropertyInfo.GetValue(viewModel, null) as SystemViewModel;

                if(systemViewModel != null)
                {
                    var admin = GetAdmin(filterContext.HttpContext.User.Identity.Name);
                    if(admin != null && _adminService.HasPermission(admin, _privilege, Access.Level.ReadWrite))
                        systemViewModel.ReadOnly = false;
                    else
                        systemViewModel.ReadOnly = true;
                }
            }
        } else if(systemViewModelPropertyInfoCount > 1)
        {
            throw new Exception("Only once instance of type SystemViewModel allowed");
        }
    }
    catch (Exception exception)
    {
        Log.Error(MethodBase.GetCurrentMethod(), exception);
        filterContext.Controller.TempData["ErrorMessage"] = string.Format("Technical error occurred");
        filterContext.Result = new RedirectResult("/Error/Index");
    }
    finally
    {
        base.OnActionExecuted(filterContext);
    }
}
4

2 に答える 2

3

別のアクションでは SalaryViewModel のようなものになる可能性があるため、このモデルを CustomerViewModel にキャストすることはできません。私が知っていることは、読み取り専用プロパティを必要とするモデルには SystemViewModel プロパティがあるということです。

オプション1

最良のオプションは、次のようなインターフェイスを作成することです。

public interface IWithSystemViewModel {
    SystemViewModel System {get;}
}

次のように、クラスからそれを実装します。

public class CustomerViewModel : IWithSystemViewModel{
    public SystemViewModel System { get;set; }
}
public class SalaryViewModel : IWithSystemViewModel{
    public SystemViewModel System { get;set; }
}

キャストしてプロパティにアクセスできますisReadOnly

IWithSystemViewModel viewModel = filterContext.Controller.ViewData.Model as IWithSystemViewModel;
if(viewModel!=null){
    viewModel.System.isReadOnly ...
}

オプション 2

リフレクションの使用に固執したい場合:

var viewModel = filterContext.Controller.ViewData.Model;
SystemViewModel  theSystem = viewModel.GetType().GetProperty("system")
    .GetValue(viewModel, null) as SystemViewModel;
theSystem.isReadOnly ...

トリッキーなこと: コードでは、タイプが であるプロパティを選択しますSystemViewModel。しかし、オブジェクトが実際にあなたの知らないいくつかのSystemViewModelプロパティを持っている場合はどうなるでしょうか? あなたは正しいものにアクセスしていますか?それらすべてに同じ名前を使用するように強制することもできますが、それは上記のオプション 1 のインターフェースを使用するようなものです。

私は間違いなくオプション1を使用します。

于 2013-04-11T12:42:58.300 に答える