1

我有一个由 WebAPI 自动序列化的对象,但我想包装它以为我的数据提供上下文。一个例子是:

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

这对我的 JSON 请求进行序列化/反序列化没有问题,一切都很好。但是,我想在允许请求完成执行之前验证其中的一些信息,所以我添加了一个 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<object> 并正确访问根目录,但它不允许这样做。到目前为止,我只能使用以下方式获取我需要的数据:

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

但是,我不想为此使用反射,而且我很难在没有答案的情况下前进。在这种情况下,我的替代方法是将数据更改为字符串并手动序列化/反序列化 JSON 对象,但这违背了在 MVC3 上使用 Web API 的某些目的。

注意: 将设计更改为以 SecureModel 作为基类会给我在数据上执行的一些散列增加挑战,所以我也不想走这条路。

谢谢!

编辑:错误的标题。

4

2 回答 2

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; }
    }
}

我们在这里使用显式接口实现,因为非泛型 ( object) 和泛型 ( T) 版本的属性Data会发生冲突。

现在,要获取信息,您可以简单地转换为ISecureModel.

于 2012-05-29T16:42:02.300 回答
1

我个人会选择创建单独的无类型接口并实现它:

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

但是,如果您可以将 getter 和 setter 拆分为单独的接口,则可以使用 C# 模板变特性:

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);
    }
}
于 2012-05-29T16:41:48.453 回答