Using <T> on IPagination - asp.net

I have the following class
public class NavigationIEntity
{
public int CurrentId { get; set; }
public string View { get; set; }
public string Controller { get; set; }
public IPagination<IEntity> Entities { get; set; }
}
I have the following helper to instantiate
public static NavigationIEntity Create<T>(int currentId, string view, string controller, IPagination<T> entities) where T : IEntity
{
return new NavigationIEntity {
Entities = entities, View = view, Controller = controller, CurrentId = currentId
};
}
However i get the following error.
EDIT: I've tried the following, "IPagination entities" ie not T
public static NavigationIEntity Create(int currentId, string view, string controller, IPagination<IEntity> entities)
{
return new NavigationIEntity { Entities = entities, View = view, Controller = controller, CurrentId = currentId };
}
but don't know how best resolve
DistributionUnit implements IEntity

You're passing a generic type into a non generic "slot". (Entities is explicitly IEntity)
Generics where is a compiler check, just checks that you're using the object right.
It does not guarantee that the object is of that type at run time.
In your case, because it's explicit anyway, you can do:
public static NavigationIEntity Create<T>(int currentId, string view, string controller, IPagination<IEntity> entities)
It will work for anything that inherits from IEntity anyway.
OR, you can do a little cheat, that will keep the signature the same, but will do what you want:
public static NavigationIEntity Create<T>(int currentId, string view, string controller, IPagination<T> entities) where T : IEntity
{
return new NavigationIEntity
{
Entities = entities as IPagination<IEntity>,
View = view,
Controller = controller,
CurrentId = currentId
};
}

Related

Out-only field in JSON deserialization [duplicate]

We have some configuration files which were generated by serializing C# objects with Json.net.
We'd like to migrate one property of the serialised class away from being a simple enum property into a class property.
One easy way to do this, would be to leave the old enum property on the class, and arrange for Json.net to read this property when we load the config, but not to save it again when we next serialize the object. We'll deal with generating the new class from the old enum separately.
Is there any simple way to mark (e.g. with attributes) a property of a C# object, so that Json.net will ignore it ONLY when serializing, but attend to it when deserializing?
There are actually several fairly simple approaches you can use to achieve the result you want.
Let's assume, for example, that you have your classes currently defined like this:
class Config
{
public Fizz ObsoleteSetting { get; set; }
public Bang ReplacementSetting { get; set; }
}
enum Fizz { Alpha, Beta, Gamma }
class Bang
{
public string Value { get; set; }
}
And you want to do this:
string json = #"{ ""ObsoleteSetting"" : ""Gamma"" }";
// deserialize
Config config = JsonConvert.DeserializeObject<Config>(json);
// migrate
config.ReplacementSetting =
new Bang { Value = config.ObsoleteSetting.ToString() };
// serialize
json = JsonConvert.SerializeObject(config);
Console.WriteLine(json);
To get this:
{"ReplacementSetting":{"Value":"Gamma"}}
Approach 1: Add a ShouldSerialize method
Json.NET has the ability to conditionally serialize properties by looking for corresponding ShouldSerialize methods in the class.
To use this feature, add a boolean ShouldSerializeBlah() method to your class where Blah is replaced with the name of the property that you do not want to serialize. Make the implementation of this method always return false.
class Config
{
public Fizz ObsoleteSetting { get; set; }
public Bang ReplacementSetting { get; set; }
public bool ShouldSerializeObsoleteSetting()
{
return false;
}
}
Note: if you like this approach but you don't want to muddy up the public interface of your class by introducing a ShouldSerialize method, you can use an IContractResolver to do the same thing programmatically. See Conditional Property Serialization in the documentation.
Approach 2: Manipulate the JSON with JObjects
Instead of using JsonConvert.SerializeObject to do the serialization, load the config object into a JObject, then simply remove the unwanted property from the JSON before writing it out. It's just a couple of extra lines of code.
JObject jo = JObject.FromObject(config);
// remove the "ObsoleteSetting" JProperty from its parent
jo["ObsoleteSetting"].Parent.Remove();
json = jo.ToString();
Approach 3: Clever (ab)use of attributes
Apply a [JsonIgnore] attribute to the property that you do not want to be serialized.
Add an alternate, private property setter to the class with the same type as the original property. Make the implementation of that property set the original property.
Apply a [JsonProperty] attribute to the alternate setter, giving it the same JSON name as the original property.
Here is the revised Config class:
class Config
{
[JsonIgnore]
public Fizz ObsoleteSetting { get; set; }
[JsonProperty("ObsoleteSetting")]
private Fizz ObsoleteSettingAlternateSetter
{
// get is intentionally omitted here
set { ObsoleteSetting = value; }
}
public Bang ReplacementSetting { get; set; }
}
For any situation where it's acceptable to have your deserialization-only property be marked internal, there's a remarkably simple solution that doesn't depend on attributes at all. Simply mark the property as internal get, but public set:
public class JsonTest {
public string SomeProperty { internal get; set; }
}
This results in correct deserialization using default settings/resolvers/etc., but the property is stripped from serialized output.
I like sticking with attributes on this one, here is the method I use when needing to deserialize a property but not serialize it or vice versa.
STEP 1 - Create the custom attribute
public class JsonIgnoreSerializationAttribute : Attribute { }
STEP 2 - Create a custom Contract Reslover
class JsonPropertiesResolver : DefaultContractResolver
{
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
//Return properties that do NOT have the JsonIgnoreSerializationAttribute
return objectType.GetProperties()
.Where(pi => !Attribute.IsDefined(pi, typeof(JsonIgnoreSerializationAttribute)))
.ToList<MemberInfo>();
}
}
STEP 3 - Add attribute where serialization is not needed but deserialization is
[JsonIgnoreSerialization]
public string Prop1 { get; set; } //Will be skipped when serialized
[JsonIgnoreSerialization]
public string Prop2 { get; set; } //Also will be skipped when serialized
public string Prop3 { get; set; } //Will not be skipped when serialized
STEP 4 - Use it
var sweet = JsonConvert.SerializeObject(myObj, new JsonSerializerSettings { ContractResolver = new JsonPropertiesResolver() });
Hope this helps! Also it's worth noting that this will also ignore the properties when Deserialization happens, when I am derserializing I just use the converter in the conventional way.
JsonConvert.DeserializeObject<MyType>(myString);
Use setter property:
[JsonProperty(nameof(IgnoreOnSerializing))]
public string IgnoreOnSerializingSetter { set { _ignoreOnSerializing = value; } }
[JsonIgnore]
private string _ignoreOnSerializing;
[JsonIgnore]
public string IgnoreOnSerializing
{
get { return this._ignoreOnSerializing; }
set { this._ignoreOnSerializing = value; }
}
Hope this help.
After i spent a quite long time searching how to flag a class property to be De-Serializable and NOT Serializable i found that there's no such thing to do that at all; so i came up with a solution that combines two different libraries or serialization techniques (System.Runtime.Serialization.Json & Newtonsoft.Json) and it worked for me like the following:
flag all your class and sub-classes as "DataContract".
flag all the properties of your class and sub-classes as "DataMember".
flag all the properties of your class and sub-classes as "JsonProperty" except those you want them not to be serialized.
now flag the properties the you do NOT want it to be serialized as "JsonIgnore".
then Serialize using "Newtonsoft.Json.JsonConvert.SerializeObject" and De-Serialize using "System.Runtime.Serialization.Json.DataContractJsonSerializer".
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Runtime.Serialization;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
namespace LUM_Win.model
{
[DataContract]
public class User
{
public User() { }
public User(String JSONObject)
{
MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(JSONObject));
DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(User));
User user = (User)dataContractJsonSerializer.ReadObject(stream);
this.ID = user.ID;
this.Country = user.Country;
this.FirstName = user.FirstName;
this.LastName = user.LastName;
this.Nickname = user.Nickname;
this.PhoneNumber = user.PhoneNumber;
this.DisplayPicture = user.DisplayPicture;
this.IsRegistred = user.IsRegistred;
this.IsConfirmed = user.IsConfirmed;
this.VerificationCode = user.VerificationCode;
this.Meetings = user.Meetings;
}
[DataMember(Name = "_id")]
[JsonProperty(PropertyName = "_id")]
public String ID { get; set; }
[DataMember(Name = "country")]
[JsonProperty(PropertyName = "country")]
public String Country { get; set; }
[DataMember(Name = "firstname")]
[JsonProperty(PropertyName = "firstname")]
public String FirstName { get; set; }
[DataMember(Name = "lastname")]
[JsonProperty(PropertyName = "lastname")]
public String LastName { get; set; }
[DataMember(Name = "nickname")]
[JsonProperty(PropertyName = "nickname")]
public String Nickname { get; set; }
[DataMember(Name = "number")]
[JsonProperty(PropertyName = "number")]
public String PhoneNumber { get; set; }
[DataMember(Name = "thumbnail")]
[JsonProperty(PropertyName = "thumbnail")]
public String DisplayPicture { get; set; }
[DataMember(Name = "registered")]
[JsonProperty(PropertyName = "registered")]
public bool IsRegistred { get; set; }
[DataMember(Name = "confirmed")]
[JsonProperty(PropertyName = "confirmed")]
public bool IsConfirmed { get; set; }
[JsonIgnore]
[DataMember(Name = "verification_code")]
public String VerificationCode { get; set; }
[JsonIgnore]
[DataMember(Name = "meeting_ids")]
public List<Meeting> Meetings { get; set; }
public String toJSONString()
{
return JsonConvert.SerializeObject(this, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore });
}
}
}
Hope that helps ...
Depending on where in the application this takes place and if it's just one property, one manual way you can do this is by setting the property value to null and then on the model you can specify that the property be ignored if the value is null:
[JsonProperty(NullValueHandling = NullValue.Ignore)]
public string MyProperty { get; set; }
If you are working on an ASP.NET Core web app, you can globally set this for all properties in all models by setting this in your Startup.cs file:
public void ConfigureServices(IServiceCollection services) {
// other configuration here
services.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore);
}
with reference to #ThoHo's solution, using the setter is actually all that is needed, with no additional tags.
For me I previously had a single reference Id, that I wanted to load and add to the new collection of reference Ids. By changing the definition of the reference Id to only contain a setter method, which added the value to the new collection. Json can't write the value back if the Property doesn't have a get; method.
// Old property that I want to read from Json, but never write again. No getter.
public Guid RefId { set { RefIds.Add(value); } }
// New property that will be in use from now on. Both setter and getter.
public ICollection<Guid> RefIds { get; set; }
This class is now backwards compatible with the previous version and only saves the RefIds for the new versions.
To build upon Tho Ho's answer, this can also be used for fields.
[JsonProperty(nameof(IgnoreOnSerializing))]
public string IgnoreOnSerializingSetter { set { IgnoreOnSerializing = value; } }
[JsonIgnore]
public string IgnoreOnSerializing;
If you use JsonConvert,IgnoreDataMemberAttribute is ok.My standard library not refrence Newton.Json,and I use [IgnoreDataMember] to control object serialize.
From Newton.net help document.
Is there any simple way to mark (e.g. with attributes) a property of a C# object, so that Json.net will ignore it ONLY when serializing, but attend to it when deserializing?
The easiest way I've found as of this writing is to include this logic in your IContractResolver.
Sample code from above link copied here for posterity:
public class Employee
{
public string Name { get; set; }
public Employee Manager { get; set; }
public bool ShouldSerializeManager()
{
// don't serialize the Manager property if an employee is their own manager
return (Manager != this);
}
}
public class ShouldSerializeContractResolver : DefaultContractResolver
{
public new static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (property.DeclaringType == typeof(Employee) && property.PropertyName == "Manager")
{
property.ShouldSerialize =
instance =>
{
Employee e = (Employee)instance;
return e.Manager != e;
};
}
return property;
}
}
All of the answers are good but this approach seemed like the cleanest way. I actually implemented this by looking for an attribute on the property for SkipSerialize and SkipDeserialize so you can just mark up any class you control. Great question!
Jraco11's answer is very neat. In case, if you want to use the same IContractResolver both for serialization and deserialization, then you can use the following:
public class JsonPropertiesResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (member.IsDefined(typeof(JsonIgnoreSerializationAttribute)))
{
property.ShouldSerialize = instance => false;
}
return property;
}
}
thats will do the trick, create a property with set only
example 1:
https://dotnetfiddle.net/IxMXcG
[JsonProperty("disabled-protections")]
public JArray DisabledProtections { set => IsPartialResult = (value != null && value.HasValues); }
public bool IsPartialResult { get; private set; }
example 2:
private JArray _disabledProtections;
[JsonProperty("disabled-protections")]
public JArray DisabledProtections { set => _disabledProtections = value; }
public bool IsPartialResult => _disabledProtections != null && _disabledProtections.HasValues;
Use [JsonIgnore] attribute in the public property of the model class.

Parse JObject into a mixed object (static + dynamic fields)

given the following json
{
"$$href": "http://localhost:8080/url1",
"name": "Sebastian Slutzky"
}
I'd like to deserialize it into an object like this one
public class DomainObject
{
[JsonProperty("$$href")]
public string href { get; set; }
public JObject this[string key] => throw new NotImplementedException();
}
so that arbitrary properties (like name can be accessed dynamically)
var href = domainObject.href;
var name = domainObject["name"] as string;
My current implementation is by passing the JObject to the constructor of my object, and decorate it (i.e. composition). Is there a way of solving this by inheritance instead (i.e. by extending JObject?
Any other solution?
You could make use of JsonExtensionData. For example
public class DomainObject
{
[JsonProperty("$$href")]
public string href { get; set; }
[JsonExtensionData]
private IDictionary<string, JToken> UnknownTypes;
public JToken this[string key] => UnknownTypes[key];
}
The Indexer now allows you to retrieve the values of dynamic properties with key as the following.
var result = JsonConvert.DeserializeObject<DomainObject>(json);
var name = result["name"].Value<string>();

Data Annotations to sanitize request and response before logging

I'm looking for a reliable solution to log details of requests and responses made to and from our controllers. However, some of the data passing through contains sensitive information that should not be written to a log.
In the controller, the inbound request is bound to a single model from the request body, and as the request is answered, a single model is passed to the Ok() result like this (very simplified):
[HttpGet]
[Route("Some/Route")]
public IHttpActionResult SomeController([FromBody] RequestType requestObj)
{
ResponseType responseObj = GetResponse(requestObj)
return this.Ok(responseObj);
}
Now my goal is to somehow log the contents of the request and response object at the beginning and end of the controller, respectively. What I would like to do is bind the models first, then log out their attributes. An example of the RequestType is something like:
public class RequestType
{
public string SomeAttribute { get; set; }
public string AnotherAttribute { get; set; }
public string Password{ get; set; }
}
And the log would look something like:
[date-time] Request to SomeController:
SomeAttribute: "value_from_request"
AnotherAttribute: "another_value"
Password: "supersecret123"
Now clearly we don't want the password to be logged. So I would like to create a custom data annotation that would not log certain fields. Its use would look like this (updated RequestType):
public class RequestType
{
public string SomeAttribute { get; set; }
public string AnotherAttribute { get; set; }
[SensitiveData]
public string Password{ get; set; }
}
Where would I start with this? I'm not incredibly familliar with .NET, but know that there are many sort of magic classes that can be subclassed to override some of their functionality. Is there any such class that can help here? Even better, is there any way to do this during the model binding? So we could catch errors that occur during model binding as well?
We should be able to achieve what you're looking for with an ActionFilterAttribute.
Capture Requests Attribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public sealed class CaptureRequestsAttribute : ActionFilterAttribute // *IMPORTANT* This is in the System.Web.Http.Filters namespace, not System.Web.Mvc
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
var messages = actionContext.ActionArguments.Select(arg => GetLogMessage(arg.Value));
var logMessage = $"[{DateTime.Now}] Request to " +
$"{actionContext.ControllerContext.Controller}]:\n{string.Join("\n", messages)}";
WriteToLog(logMessage);
base.OnActionExecuting(actionContext);
}
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
var result = actionExecutedContext.Response.Content as ObjectContent;
var message = GetLogMessage(result?.Value);
var logMessage = $"[{DateTime.Now}] Response from " +
$"{actionExecutedContext.ActionContext.ControllerContext.Controller}:\n{message}";
WriteToLog(logMessage);
base.OnActionExecuted(actionExecutedContext);
}
private static void WriteToLog(string message)
{
// todo: write you logging stuff here
}
private static string GetLogMessage(object objectToLog)
{
if (objectToLog == null)
{
return string.Empty;
}
var type = objectToLog.GetType();
var properties = type.GetProperties();
if (properties.Length == 0)
{
return $"{type}: {objectToLog}";
}
else
{
var nonSensitiveProperties = type
.GetProperties()
.Where(IsNotSensitiveData)
.Select(property => $"{property.Name}: {property.GetValue(objectToLog)}");
return string.Join("\n", nonSensitiveProperties);
}
}
private static bool IsNotSensitiveData(PropertyInfo property) =>
property.GetCustomAttributes<SensitiveDataAttribute>().Count() == 0;
}
Sensitive Data Attribute
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public sealed class SensitiveDataAttribute : Attribute
{
}
Then, you can just add it to your WebApi controller (or a specific method in it):
[CaptureRequests]
public class ValuesController : ApiController
{
// .. methods
}
And finally your models can just add the SensitiveDataAttribute:
public class TestModel
{
public string Username { get; set; }
[SensitiveData]
public string Password { get; set; }
}
This does not make use of DataAnnotations,however, One way that comes to mind would be to use the serialization. If your payload is within a reasonable size you could serialize and deserialize your RequestType class when reading and writing to/from a log. This would require a custom serialization format or making use of the default, xml.
[Seriliazeble()]
public class RequestType
{
public string SomeAttribute { get; set; }
public string AnotherAttribute { get; set; }
[NonSerialized()]
public string Password{ get; set; }
}
Using the above attribute will omit Password from serialization. Then you copuld proceed to Logger.Log(MySerializer.Serialize(MyRequest)); and your sensitive data will be omitted.
This link describes the approach in detail.
For xml serialization, simply use the XmlSerializer class.
public class MySerializationService
{
public string SerializeObject(object item)
{
XmlSerializer serializer = new XmlSerializer(item.GetType());
System.IO.MemoryStream aMemStr = new System.IO.MemoryStream();
System.Xml.XmlTextWriter writer = new System.Xml.XmlTextWriter(aMemStr, null);
serializer.Serialize(writer, item);
string strXml = System.Text.Encoding.UTF8.GetString(aMemStr.ToArray());
return strXml;
}
public object DeSerializeObject(Type objectType, string objectString)
{
object obj = null;
XmlSerializer xs = new XmlSerializer(objectType);
obj = xs.Deserialize(new StringReader(objectString));
return obj;
}
}
Then using the above or similar methods you can read and write in a custom format.
Write :
string logData=new MySerializationService().SerializeObject(myRequest);
Read :
RequestType loggedRequest= (RequestType)new MySerializationService().DeSerializeObject(new RequestType().GetType(), logData);

Web API error failed to serialize the response body

Im fairly new to ASP.NET MCV 4 as well as Mongo DB and trying to build web API.
I thought I had finally got it right but when I start the app and enter: http://localhost:50491/api/document into my browser I get this error message
The 'ObjectContent`1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.
Here is my code
This is the Document Class
public class Document
{
[BsonId]
public ObjectId DocumentID { get; set; }
public IList<string> allDocs { get; set; }
}
This is where the Connection to the DB is made:
public class MongoConnectionHelper
{
public MongoCollection<BsonDocument> collection { get; private set; }
public MongoConnectionHelper()
{
string connectionString = "mongodb://127.0.0.1";
var server = MongoServer.Create(connectionString);
if (server.State == MongoServerState.Disconnected)
{
server.Connect();
}
var conn = server.GetDatabase("cord");
collection = conn.GetCollection("Mappings");
}
Here is the ApiController Class:
public class DocumentController : ApiController
{
public readonly MongoConnectionHelper docs;
public DocumentController()
{
docs = new MongoConnectionHelper();
}
public IList<BsonDocument> getAllDocs()
{
var alldocs = (docs.collection.FindAll().ToList());
return alldocs;
}
}
I read futher on and the error message suggested:
Type 'MongoDB.Bson.BsonObjectId' with data contract name 'BsonObjectId:http://schemas.datacontract.org/2004/07/MongoDB.Bson' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
That is all good and well but how do I do that?
Either a) don't serialize your document classes over Web API, and create some DTOs meant to be serialized, or b) use something else as ID.
If you want an easy auto-generated ID, and you're OK with the fact that it will consume slightly more space, you can resort to the following "hack":
public class Document
{
public Document()
{
Id = ObjectId.GenerateNewId().ToString();
}
public string Id { get; set; }
}
This way, you'll get MongoIDs, but they'll be stored as a string.
If you need Web API2 responce in XML format , you need to handle the default Id like below
eg: ObjectId("507f191e810c19729de860ea")
Either you need to remove the Id from serialization.
[DataContract]
public class Document
{
[BsonId]
public string Id { get; set; }
[DataMember]
public string Title { get; set; } //other properties you use
}
Or You can change the Type of ID with custom logic
public class GuidIdGenerator : IIdGenerator
{
public object GenerateId(object container, object document)
{
return Guid.NewGuid();
}
public bool IsEmpty(object id)
{
return string.IsNullOrEmpty(id.ToString());
}
}
public class Document
{
[BsonId(IdGenerator = typeof(GuidIdGenerator))]
public string Id { get; set; }
public string Title { get; set; } //other properties you use
}

How do i get Intellisense for <T> class?

i'm creating an html.helper for a 3rd party javascript grid component. i'm passing my gridextension my viewmodel.
in my viewmodel class i've got custom attributes on my properties describing how each column is displayed.
in my gridextension, i want to then serialize my class of T. in my CreateSerializedRow method i'd like to be able to do something like row. <- and get intellisense for my class. but how to i get intellisense for the members of class T without an explicit cast?
public class GridData<T>
{
#region Fields
private List<Dictionary<string, object[]>> _attributes;
private static IList<T> _dataSource;
#endregion
#region Properties
public string Align { get; set; }
public string Header { get; set; }
public string JsonData { get; set; }
public string Sorting { get; set; }
public string Width { get; set; }
#endregion
#region Public Methods
public void Serialize(IList<T> dataSource, List<Dictionary<string, object[]>> attributes)
{
_dataSource = dataSource;
_attributes = attributes;
JsonData = _dataSource.Count == 0 ? string.Empty : BuildJson();
}
#endregion
#region Private Methods
private static string BuildJson()
{
var sbJson = new StringBuilder();
var listCount = _dataSource.Count;
sbJson.Append("{page: 1, total:" + listCount + ", rows: [");
for (var i = 0; i < listCount; i++)
{
var serialized = CreateSerializedRow(i);
sbJson.Append(serialized);
if (i < listCount - 1)
sbJson.Append(",");
}
sbJson.Append("]}");
return sbJson.ToString();
}
private static string CreateSerializedRow(int index)
{
var row = _dataSource[index];
var sb = new StringBuilder();
//sb.Append("{id:'" + Id + "',data:[");
//sb.Append(String.Format("'{0}',", GroupName.RemoveSpecialChars()));
//sb.Append(String.Format("'{0}',", Description));
//sb.Append(String.Format("'{0}',", CreatedBy));
//sb.Append(String.Format("'{0}',", CreatedDate.ToShortDateString()));
//sb.Append(String.Format("'{0}',", EmailSubject.RemoveSpecialChars()));
//sb.Append(String.Format("'{0}',", EmailBody));
//sb.Append(String.Format("'{0}',", UpdatedBy));
//sb.Append(String.Format("'{0}'", UpdatedDate.ToShortDateString()));
//sb.Append("]}");
return sb.ToString();
}
#endregion
}
The best you can do is use Generic constraints, which specify that T must be castable to a specific type. See http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx#csharp_generics_topic4 for more information.
The syntax is more or less the following:
public class MyClass<T> where T : ISomethingOrOther
{
}
At least this way, you can limit T to an interface type and code against that abstraction with Intellisense support.
With what you're trying to do you'd probably have to use reflection to cycle through the properties and output the values. You might be better off making GridData an abstract class and override a method which outputs the row of data for each data class.
Or create a generic interface which has a Serialize() method that outputs a string of the objects values in the expected format. Have each model class implement this interface and then have the GridData class constrained to this interface. Assuming these are ViewModel classes, it should be a reasonable design.
If T is always a known interface or class you can do:
public class GridData<T>
where T:MyClass
{
...
}

Resources