I have defined such a function:

public static void WriteResponse(ref HttpContext ctx, object sender, Type typeName)
{
    var model = sender as typeName; // it's an error-line, becase of `as typeName`
    var jsonObject = new JavaScriptSerializer().Serialize(model);
    ctx.Response.AddHeader("Access-Control-Allow-Origin", "*");
    ctx.Response.ContentType = "Content-type: application/json";
    ctx.Response.ContentEncoding = Encoding.UTF8;
    ctx.Response.Write(jsonObject);
}

As you can see, it wouldn't even compile, becase of the line:

var model = sender as typeName;

I'm calling this function from that one:

internal void GetShortInfo(ref HttpContext ctx, ref Shapefile shapefile)
{
    var model = new Models.SfShortInfo()
    {
        Count = shapefile.Count,
        Type = shapefile.Type.ToString()
    };

    ShapefileService.WriteResponse(ref ctx, (object)model, model.GetType());
}

And such a call:

ShapefileService.WriteResponse(ref ctx, (object)model, model.GetType());

I want to add to any function from self-designed API Web-service.

I think, that you've got an idea, what I'm trying TO DO.

I want to define one function, that could accept calls from various number of other functions by boxing the model instance to System.Object and unboxing it for the JSON-response.

It's similar to reinterpret_cast<> function in C++. I think, that I could done it in C# with the Generics, but I don't know very well that part of C#, so I'm advicing your help.

Thanks!

有帮助吗?

解决方案 4

You don't need cast at all. The JavaScriptSerializer.Serialize method has this prototype:

public string Serialize(Object obj)

This means that your "unboxed" model will be boxed again and than you don't have to do this. Internally the function use Reflection and is able to read all Model metadata even it is passed to the method as object.

Using ref for HttpContext is not necessary and it is little bit dangerous because HttpContext is reference type and you can change reference in the called method. I have never seen good reason for pass reference type with ref keyword. It is useful mainly with value types.

Your solution can looks like:

public static void WriteResponse(HttpContext ctx, object model)
{
    string jsonObject = new JavaScriptSerializer().Serialize(model);
    ctx.Response.AddHeader("Access-Control-Allow-Origin", "*");
    ctx.Response.ContentType = "Content-type: application/json";
    ctx.Response.ContentEncoding = Encoding.UTF8;
    ctx.Response.Write(jsonObject);
}

Second point is that you don't have to cast model to object and you can pass model directly:

ShapefileService.WriteResponse(ctx, model);

If you really need strong type in the WriteResponse method, than you can use generic method:

public static void WriteResponse<T>(HttpContext ctx, T model)
{
    string jsonObject = new JavaScriptSerializer().Serialize(model);
    ctx.Response.AddHeader("Access-Control-Allow-Origin", "*");
    ctx.Response.ContentType = "Content-type: application/json";
    ctx.Response.ContentEncoding = Encoding.UTF8;
    ctx.Response.Write(jsonObject);
}

ShapefileService.WriteResponse<Models.SfShortInfo>(ctx, model);

其他提示

This is a problem not to be fixed, but to be avoided. In fact, casting model to one type or the other with be useless, because it will become an object again when you pass it to Serialize.

Just remove this line from your code entirely:

var model = sender as typeName;

JavaScriptSerializer will take care of all the details.

This will work.. but you should be aware that this is much more type safe than what you're probably expecting (given you bring up reinterpret_cast):

 var model = Convert.ChangeType(sender, typeName);

You can expect exceptions to be thrown if you're just going to randomly throw type's at it.

The usual approach would be static polymorphism:

public static void WriteResponse<T>(ref HttpContext ctx, object sender) 
    where T : class
{
    var model = sender as T;

    // ...
}

where T : class because T needs to be of reference type AFAIR. If it need not be, switch to a 'hard' cast:

    var model = (T) sender;

Or, you can make the whole cast implicit (thanks @Aik for pointing it out)

public static void WriteResponse<T>(ref HttpContext ctx, T model) 
{
    // ...
}

By using generics in C# you could code it as such:

public static void WriteResponse<T>(HttpContext ctx, T sender)
{
    var jsonObject = new JavaScriptSerializer().Serialize(sender);
    ctx.Response.AddHeader("Access-Control-Allow-Origin", "*");
    ctx.Response.ContentType = "Content-type: application/json";
    ctx.Response.ContentEncoding = Encoding.UTF8;
    ctx.Response.Write(jsonObject);
}

internal void GetShortInfo(HttpContext ctx, Shapefile shapefile)
{
    var model = new Models.SfShortInfo
    {
        Count = shaefile.Count,
        Type = shapefile.Type.ToString()
    };

    ShapefileService.WriteResponse(ctx, model);
}

This way there isn't any need to do any casting because it will come into the function as the type it already needs to be known as.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top