2012-05-29 32 views
1

我有一個對象被WebAPI自動序列化,但我想包裝它以爲我的數據提供上下文。一個例子是:動態鍵入一個通用類

public class SecureModel<T> 
{ 
    public string Info { get; set; } 
    public T Data { get; set; } 
} 

這個序列化/反序列化沒有問題與我的JSON請求,一切都很好。但是,我想在允許請求完成執行之前驗證一些Info,所以我添加了一個ActionFilter,用於檢索POST的參數。

public class MyAuth : System.Web.Http.Filters.ActionFilterAttribute 
{ 
    public override void OnActionExecuting(HttpActionContext actionContext) 
    { 
    var arg = actionContext.ActionArguments.FirstOrDefault().Value; 
    // arg: get the Info? 
    // if the info isn't correct, return a specific Response. 
    } 
} 

當我檢查的說法,這正是我需要的,但我無法弄清楚如何弱它不指定實際泛型類型鍵入SecureModel。我覺得我應該能夠對SecureModel <對象>這樣做,並正確地訪問根目錄,但它不允許這樣做。到目前爲止,我只能得到我需要使用數據:

var notStrongEnough = arg.GetType().GetProperty("Info"); 

不過,我寧願不使用反射,這和我有一個很難前進沒有答案。在這種情況下,我的替代方法是將數據更改爲字符串,並手動序列化/反序列化JSON對象,但是這違背了使用Web API而不是MVC3的一些目的。

Note:更改設計以將SecureModel作爲基類增加了我對數據執行的一些散列的挑戰,因此我寧願不要沿着這條路徑走。

謝謝!

編輯:錯誤標題。

+0

爲什麼不嘗試動態arg = actionContext.ActionArguments.FirstOrDefault()。值 –

+0

在C#中,有泛型,但沒有模板。這些是不同的編程模型。 –

回答

3

C#中這類問題的典型解決方案是創建泛型類型實現的非泛型接口。例如,你的類:

public class SecureModel<T> 
{ 
    public string Info { get; set; } 
    public T Data { get; set; } 
} 

你可以定義一個接口,ISecureModel

public interface ISecureModel 
{ 
    string Info { get; } 
    object Data { get; } 
} 

現在你可以在你的數據類實現它:

public class SecureModel<T> : ISecureModel 
{ 
    public string Info { get; set; } 
    public T Data { get; set; } 

    object ISecureModel.Data { 
     get { return Data; } 
    } 
} 

我們使用顯式接口實現,因爲屬性Data的非通用(object)和通用(T)版本會以其他方式共享llide。

現在,要獲取信息,您可以簡單地投到ISecureModel

+0

正是我想提出的:) – ivowiblo

1

個人而言,我會選擇創建單獨的類型化接口,並實現它:

interface IObjectTypeSercureModel 
{ 
    object GetData(); 
    string GetInfo(); 
} 

但是,它可以分裂getter和setter成獨立的接口,這將有可能使用C#模板co-variance特點:

public interface IReadModel<out T> 
{ 
    T Data {get;} 
    string Info { get; } 
} 
public interface IWriteModel<in T> 
{ 
    T Data { set; } 
    string Info { set; } 
} 
public class SecureModel<T> : IReadModel<T>, IWriteModel<T> 
{ 
    public string Info { get; set; } 
    public T Data { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var m = new SecureModel<string>(); 
     m.Data = "test"; 

     IReadModel<object> genericRead = (IReadModel<object>)m; 
     Console.WriteLine(genericRead.Data); 
    } 
}