How can I query different tables dynamically with LINQ? - c#

So I'm not sure if you can do this or not, but I would like to avoid using SQL strings if I can. What I would like to do with Linq/DbContexts is the following that can be done easily with SQL:
string sql = "UPDATE " + tableName + " SET Status=0 WHERE Id=" + formId.ToString();
I can easily put this into a loop where tableName and formId are given dynamically and execute no problem.
I have multiple DbContexts, so I don't know of any way to do something like:
var db = new *dynamicallyChosenContext*()
var query = from p in db.*dynamicallyChosenAlso*
where p.Id == formId
select p;
foreach (var result in query)
{
result.Status = 0;
}
db.SaveChanges()
Thanks for the help!

Here is a piece of working code that can update different tables at runtime from different contexts without using reflection.
namespace DemoContexts
{
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
public interface IThing
{
int Id { get; set; }
int Status { get; set; }
}
public class FirstPersonThing : IThing
{
[System.ComponentModel.DataAnnotations.Key]
public int Id { get; set; }
public int Status { get; set; }
public string Foo { get; set; }
}
public class SecondPersonThing : IThing
{
[System.ComponentModel.DataAnnotations.Key]
public int Id { get; set; }
public int Status { get; set; }
public string Bar { get; set; }
}
public class FirstContext : DbContext
{
public FirstContext() : base("FirstContext") { }
public DbSet<FirstPersonThing> MyThings { get; set; }
public DbSet<SecondPersonThing> YourThings { get; set; }
}
public class SecondContext : DbContext
{
public SecondContext() : base("SecondContext") { }
public DbSet<FirstPersonThing> MyThings { get; set; }
public DbSet<SecondPersonThing> YourThings { get; set; }
}
class Program
{
static void Main(string[] args)
{
int contextType = 1;
int thingType = 1;
DbContext db = RunTimeCreatedContext(contextType);
IQueryable<IThing> collection = RunTimeCreatedCollection(db, thingType);
UpdateRuntimeDeterminedThings(db, collection, 1);
Console.ReadLine();
}
public static void UpdateRuntimeDeterminedThings(DbContext db,
IQueryable<IThing> collection,
int formId)
{
var querySet = collection.Where(p => p.Id == formId).ToList();
foreach (var result in querySet)
{
result.Status = 0;
}
db.SaveChanges();
}
static DbContext RunTimeCreatedContext(int contextType)
{
if (contextType == 0)
{
return new FirstContext();
}
else
{
return new SecondContext();
}
}
static IQueryable<IThing> RunTimeCreatedCollection(DbContext db, int thingType)
{
if (thingType == 0)
{
return db.Set(typeof(FirstPersonThing)) as IQueryable<IThing>;
}
else
{
return db.Set<SecondPersonThing>();
}
}
}
}
The first thing to note is that all this is statically typed so to perform a generic query against different types of objects these objects must have common property signatures and this conceptually is expressed in the IThing interface.
A second thing to note is how the IQueryable is generated. It is generated by the DbContext.Set Method (Type) in the first instance (for the FirstPersonThings), it is generated by the DbContext.Set<TEntity> Method in the second instance. The first uses a type determined at runtime and requires a cast (but could be useful to use passing types at runtime), the second uses generics and the types are determined at compile time. There are obviously a number of other ways that this function could work.
Finally the method UpdateRuntimeDeterminedThings works because it uses properties and methods that are shared across the types (either with base types/inheritance or by the implementation of interfaces).
None of this is actually dynamic programming (which is possible using the dynamic type) and I have used the term runtime determined rather than dynamic to describe how this works.

There is a technique in functional programming, called Currying, where you could pass as much parameters as you want, so you are able to access them.
Here is an exemple: http://blogs.msdn.com/b/sriram/archive/2005/08/07/448722.aspx
P.S: You could use a currying function to iterate through yours DBContexts.

I think you have to use reflection if you want to use 'code' and not sql strings. That's just how C# works... This is how you could do it:
using System;
using System.Data.Entity;
using System.Linq;
public class TestContext : DbContext
{
public DbSet<Box> Boxes { get; set; }
public DbSet<Thing> Things { get; set; }
}
public abstract class Base
{
public int Id { get; set; }
}
public class Box : Base
{
public string Title { get; set; }
}
public class Thing : Base
{
public string Name { get; set; }
}
internal class Program
{
private static void Main(string[] args)
{
var db = new TestContext();
DoIt(GetPropValue(db, "Boxes") as IQueryable<Base>);
DoIt(GetPropValue(db, "Things") as IQueryable<Base>);
}
private static void DoIt(IQueryable<Base> b)
{
Console.WriteLine(
b.Single(t => t.Id == 1).Id);
}
private static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
}
Obviously you can then put the strings in a list etc, whatever you need.

Related

How to define a type whose gender can be changed on the fly in code without changing the type of all the properties that are of its type?

I have many entities that use a UserId property of the same type.
Can I define a type (string or int, ...) that I can easily change as a variant for all?
Example:
public class Entity_One
{
public DefineMyType UserId { get; set; }
public string Property_Entity_One { get; set; }
}
public class Entity_Two
{
public DefineMyType UserId { get; set; }
public string Property_Entity_Two { get; set; }
}
const DefineMyType = string;
// or const DefineMyType = int;
// or const DefineMyType = Guid;
Constants can't be used like that.
Preprocessor may be used.
But we can use a generic:
public abstract class AbstractID<T>
{
static protected T Last = default;
public T Value { get; protected set; } // or perhaps init only with C# 9
}
Thus we can define some specialized IDs like:
public class NumberID<T> : AbstractID<T> where T : struct, IComparable, IFormattable
{
public NumberID()
{
Value = (T)( (dynamic)Last + 1 );
Last = Value;
}
}
public class GuidID : AbstractID<Guid>
{
public GuidID()
{
Value = Guid.NewGuid();
Last = Value;
}
}
public class StringID : AbstractID<string>
{
private string Generate()
{
return ...
}
public StringID()
{
Value = Generate();
Last = Value;
}
}
Then we can set the "default" ID type:
public class ManagedID : NumberID<int>
{
}
Or:
public class ManagedID : GuidID
{
}
Therefore we can easily change ManagedID for all code using it.
It only requires to change the ancestor class in the declaration.
And now that works:
public class EntityOne
{
public ManagedID UserId { get; } = new ManagedID();
public string PropertyEntityOne { get; set; }
}
public class EntityTwo
{
public ManagedID UserId { get; } = new ManagedID();
public ManagedID EntityOneId { get; }
public string PropertyEntityTwo { get; set; }
public EntityTwo(EntityOne one)
{
EntityOneId = one.UserId;
}
}
Test
var entity1 = new EntityOne();
var entity2 = new EntityOne();
var entity3 = new EntityTwo(entity1);
Console.WriteLine(entity1.UserId.Value);
Console.WriteLine(entity2.UserId.Value);
Console.WriteLine(entity3.UserId.Value + $" ({entity3.EntityOneId.Value})");
Result with an integer
1
2
3 (1)
Result with a GUID
3a189122-60fd-4dc5-9d7f-3cc4c83375f9
37a9c7de-8ed5-4d02-a1b9-f414db051335
2de962d6-cc91-4e78-b3dc-28acb0ba7f3b (3a189122-60fd-4dc5-9d7f-3cc4c83375f9)
Warning
Here, the use of numbers is very basic and not really reliable, especially beyond a local machine and after stopping the execution of the current process. Thus persistence somewhere of the last value is required for a real database, like in a config file or whatever.
GUID vs INT IDENTITY
Guid vs INT - Which is better as a primary key?
Int for identity/primary key and Guid for public identifier, best practices?

No properties are mapped for type using csvHelper

I have two methods that return list of EmployeeCsv and CardCsv.
public class EmployeeCsv
{
public string EmployeeId { get; set; }
public string EmployeeName { get; set; }
}
public class CardCsv
{
public string MaxCharge { get; set; }
public string MaxDiscount { get; set; }
}
public List<EmployeeCsv> GetEmployeeList() {} // returns list of EmployeeCsv
public List<CardCsv> GetCardList() {} // returns list of CardCsv
I wanted to declare one type list for those two methods.
So I changed them like below
public interface ITest {}
public class EmployeeCsv : ITest
{
public string EmployeeId { get; set; }
public string EmployeeName { get; set; }
}
public class CardCsv : ITest
{
public string MaxCharge { get; set; }
public string MaxDiscount { get; set; }
}
public List<ITest> GetEmployeeList() {}
public List<ITest> GetCardList() {}
Main:
void main()
{
var records = new List<ITest>();
records = GetEmployeeList();
using (var writer = new StreamWriter(fileName))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
csv.Configuration.ShouldQuote = (field, context) => true;
csv.WriteRecords(records); // error here
}
}
I get an error on saving after adding interface to those two classes.
How can I fix this?
The problem here is that CsvHelper doesn't know the instance of the list items. You're telling it to process ITest items.
Consider the following:
var records = new List<ITest> { new EmployeeCsv(), new CardCsv() };
This is valid code. Now put yourself in CsvHelper's position. How would it create a CSV out of the items? Would it handle them as Employee, or Card? Neither. All it knows is that the items were ITest (a blank interface). Hence your error.
Instead complicating it with ITest, you're better off leaving the list items as their concrete types, but treating them as IEnumerable.
// Leave them as the derived types
public List<EmployeeCsv> GetEmployeeList() { .. }
public List<CardCsv> GetCardList() { .. }
void Main() {
// Notice the IEnumerable so we can reuse WriteToFile()
IEnumerable items = GetEmployeeList();
WriteToFile(items); // employees
items = GetCardList();
WriteToFile(items); // cards
}
void WriteToFile(IEnumerable records) {
...
csv.WriteRecords(records);
}
This way, CsvHelper can actually inspect the list and figure out the type, without the ITest confusion.
Edit:
You should probably create a generic method, that way you can limit your items to ITest if you really want to, or you can leave it open.
// This needs to stay as its concrete type.
public List<EmployeeCsv> GetEmployeeList() { .. }
void Main() {
WriteToFile(GetEmployeeList());
}
// Get rid of the 'where' to make it accept things other than ITest.
void WriteToFile<T>(IEnumerable<T> records) where T : ITest
{ ...
csv.WriteRecords(records);
}

How to use interface from entity framework database first auto-generated code

I have the following two classes auto generated with Entity Framework using database first;
public partial class UserXml
{
public UserXml()
{
this.UserXmlHotel = new HashSet<UserXmlHotel>();
}
public long UserId { get; set; }
public string Password { get; set; }
public bool Enabled { get; set; }
public byte FailedAttempt { get; set; }
public virtual User User { get; set; }
public virtual UserXmlIp UserXmlIp { get; set; }
public virtual ICollection<UserXmlHotel> UserXmlHotel { get; set; }
}
and
public partial class UserCustomer
{
public UserCustomer ()
{
this.UserCustomerHotel = new HashSet<UserCustomerHotel >();
}
public long UserId { get; set; }
public bool Enabled { get; set; }
public string Password { get; set; }
}
I've then created the following classes;
public partial class UserXml : IUser
{
}
public partial class UserCustomer : IUser
{
}
public static class EntityExtensions
{
public static IQueryable<T> Enabled<T>(this IQueryable<T> source) where T : IUser
{
return source.Where(x => x.Enabled);
}
}
I have a interface as;
public interface IUser
{
bool Enabled { get; }
}
Want I'm wanting to do is combine the same call for each entity using the same re-usable code; So take
using(var Context = new EscapeEntities())
{
bool bEnabled = Context.UserXml.First(u => u.UserId == iUserId).Enabled;
}
and
using(var Context = new EscapeEntities())
{
bool bEnabled = Context.UserCustomer.First(u => u.UserId == iUserId).Enabled;
}
I'm wanting to use my EntityExtensions class, but I'm having trouble getting it to work. Any pointers ?
When you use expressions on generic types which implement an interface, the expression builder adds a cast to the expression, like below:
x => x.Enabled // converts to something like below:
x => ((IUser)x).Enabled
So what you need to do is to tell the expression builder to not add the cast expression by defining your generic type as a class, which means your Enabled(...) extension method needs to be like this:
public static IQueryable<T> Enabled<T>(this IQueryable<T> source)
where T : class, IUser // added 'class' constraint
{
return source.Where(x => x.Enabled);
}
Another approach (which needs much more work) is to define an ExpressionVisitor class to remove the convert on the expression which is explained on this stackoverflow answer.
So after this correction, you can user your extension method easily:
using(var Context = new EscapeEntities())
{
IQueryable<UserXml> query = Context.UserXml
.Where(u => u.Password == "Foo")).Enabled();
List<UserXml> res = query.ToList();
}
P.S. I think you'd be better off with defining another extra "base" User table with two children named UserXml and UserCustomer and abstract out the common columns into User table, which removes the need for extra interfaces and is also compatible with object oriented design.

How to use the same foreach code for 2 collections?

I have 2 collections of 2 different types but have almost the same set of fields.
in one function, I need to iterate through one of the collections depending on one condition.
I want to write only one code block that will cover both cases.
Example:
I have the following code:
if (condition1)
{
foreach(var type1var in Type1Collection)
{
// Do some code here
type1var.Notes = "note";
type1var.Price = 1;
}
}
else
{
foreach(var type2var in Type2Collection)
{
// the same code logic is used here
type2var.Notes = "note";
type2var.Price = 1;
}
}
Now: I want to simplify this code to use the same logic only once ( as they are identical ), something like the following ( P.S : I know the following code is not correct, I am just explaining what I want to do ):
var typecollection = Condition1 ? Type1Collection : Type2Collection;
foreach(var typevar in TypeCollection)
{
// the same code logic is used here
typevar.Notes = "note";
typevar.Price = 1;
}
The definition of Type1 & Type2 is similar to the following code ( Actually they are Entity objects):
public class Type1 : EntityObject
{
public int Type1ID { get; set; }
public int Type1MasterID { get; set; }
public String Notes { get; set; }
public decimal Price { get; set; }
}
public class Type2 : EntityObject
{
public int Type2ID { get; set; }
public int Type2MasterID { get; set; }
public String Notes { get; set; }
public decimal Price { get; set; }
}
Update 1:
I have included some sample code I am using inside foreach block ( I am accessing a public properties of the 2 types).
Update 2:
I have included sample Type1 & Type2 definitions, as you can see I have 2 common Public Properties in both classes which I want to update in foreach block.
Update 3:
I am sorry for the confusion, Type1 & Type2 are derived from EntityObject ( They are both part of my entity model, and the Type1Collection & Type2Collection are actually EntityCollection of these 2 entities.
You could use dynamic. Note you will lose type safety.
var list1 = new List<bool>(){true,false};
var list2 = new List<int>(){1,2};
var typecollection = condition1 ? list1.Cast<dynamic>() : list2.Cast<dynamic>();
foreach (var value in typecollection)
{
//then you can call a method you know they both have
Debug.WriteLine(value.ToString());
}
Or if they share a common interface you can cast directly to that. You will maintain type safety
var list1 = new List<bool>(){true,false};
var list2 = new List<int>(){1,2};
var typecollection = condition1 ? list1.Cast<IConvertible>() : list2.Cast<IConvertible>();
foreach (IConvertible convertible in typecollection)
{
//we now know they have a common interface so we can call a common method
Debug.WriteLine(convertible.ToString());
}
Given Jon Skeet's hint of using LINQ's Concat method and the OP's statement that the classes involved are EntityObjects, here's another possible solution. This assumes that the EntityObject subclasses are defined as partial classes:
public partial class Type1 : EntityObject
{
public int Type1ID { get; set; }
public int Type1MasterID { get; set; }
public String Notes { get; set; }
public decimal Price { get; set; }
}
public partial class Type2 : EntityObject
{
public int Type2ID { get; set; }
public int Type2MasterID { get; set; }
public String Notes { get; set; }
public decimal Price { get; set; }
}
This allows the OP to declare an interface with the common properties, and have his EntityObject subclasses implement that interface:
public interface IMyType
{
String Notes { get; set; }
decimal Price { get; set; }
}
public partial class Type1 : IMyType {}
public partial class Type2 : IMyType {}
And the original code becomes:
var query = (
from type1var in type1Collection
where condition1
select (IMyType)type1var
).Concat(
from type2var in type2Collection
where !condition1
select (IMyType)type2var
);
foreach(var myType in query)
{
myType.Notes = "note";
myType.Price = 1;
}
You could create a base type for type1 and type2 that groups the common properties between the two classes:
class MyBaseType {
// Common properties
}
class Type1 : MyBaseType {
// Specific properties
}
class Type2 : MyBaseType {
// Specific properties
}
Then, you could do something like this:
IEnumerable<MyBaseType> collection;
if(condition1)
collection = type1Collection;
else
collection = type2Collection;
foreach(MyBaseType element in collection) {
// Common logic
}
EDIT:
As Simon points out in the comments, you should use an interface instead of a base type if it's enough (i.e you don't need a specific implementation for both types).
This is not a very nice way to do it, but it would atleast work.
var type1Collection = new Collection<Type1>();
var type2Collection = new Collection<Type2>();
var condition1 = new Random().Next(0, 2) != 0;
dynamic selectedCollection;
if (condition1)
selectedCollection = type1Collection;
else
selectedCollection = type2Collection;
foreach (var typeVar in selectedCollection)
{
typeVar.Notes = "note";
typeVar.Price = 1;
}
I'm surprised nobody else has suggested an extension method yet:
public interface IMyType
{
String Notes { get; set; }
decimal Price { get; set; }
}
public static class MyTypeExtensions
{
public static void MyLogic(this IMyType myType)
{
// whatever other logic is needed
myType.Notes = "notes";
myType.Price = 1;
}
}
Now, your original types just need to implement IMyType:
public class Type1 : IMyType
{
public int Type1ID { get; set; }
public int Type1MasterID { get; set; }
public String Notes { get; set; }
public decimal Price { get; set; }
}
public class Type2 : IMyType
{
public int Type2ID { get; set; }
public int Type2MasterID { get; set; }
public String Notes { get; set; }
public decimal Price { get; set; }
}
Then the original code becomes:
if (condition1)
{
foreach (var type1 in type1Collection)
{
type1.MyLogic();
}
}
else
{
foreach (var type2 in type2Collection)
{
type2.MyLogic();
}
}
You can do it with Predicate and Action stored in a Dictionary. I am suggesting Action here since the code snippet doesn't seems to return anything
public class IterationExample
{
private readonly Dictionary<bool, Action> dictionary;
public IterationExample()
{
dictionary = new Dictionary<bool, Action> { { true, CollectionOneIterator }, { false, CollectionTwoIterator } };
}
public void PublicMethod()
{
dictionary[condition]();
}
private void CollectionOneIterator()
{
foreach (var loopVariable in Type1Collection)
{
//Your code here
}
}
private void CollectionTwoIterator()
{
foreach (var loopVariable in Type2Collection)
{
//Your code here
}
}
}
With this way the readbility and testability of your code improves and also avoids long methods.
Edit:
public class Entity
{
public IList<string> Type1Collection { get; set; }
public IList<string> Type2Collection { get; set; }
}
public class ConsumingClass
{
public void Example()
{
var entity = new Entity();
entity.PublicMethod();
}
}
public static class IterationExample
{
private static readonly Dictionary<bool, Action<Entity>> dictionary;
static IterationExample()
{
dictionary = new Dictionary<bool, Action<Entity>> { { true, CollectionOneIterator }, { false, CollectionTwoIterator } };
}
public static void PublicMethod(this Entity entity)
{
dictionary[condition]();
}
private static void CollectionOneIterator(Entity entity)
{
foreach (var loopVariable in entity.Type1Collection)
{
//Your code here
}
}
private static void CollectionTwoIterator(Entity entity)
{
foreach (var loopVariable in entity.Type2Collection)
{
//Your code here
}
}
}

C# - copying property values from one instance to another, different classes

I have two C# classes that have many of the same properties (by name and type). I want to be able to copy all non-null values from an instance of Defect into an instance of DefectViewModel. I was hoping to do it with reflection, using GetType().GetProperties(). I tried the following:
var defect = new Defect();
var defectViewModel = new DefectViewModel();
PropertyInfo[] defectProperties = defect.GetType().GetProperties();
IEnumerable<string> viewModelPropertyNames =
defectViewModel.GetType().GetProperties().Select(property => property.Name);
IEnumerable<PropertyInfo> propertiesToCopy =
defectProperties.Where(defectProperty =>
viewModelPropertyNames.Contains(defectProperty.Name)
);
foreach (PropertyInfo defectProperty in propertiesToCopy)
{
var defectValue = defectProperty.GetValue(defect, null) as string;
if (null == defectValue)
{
continue;
}
// "System.Reflection.TargetException: Object does not match target type":
defectProperty.SetValue(viewModel, defectValue, null);
}
What would be the best way to do this? Should I maintain separate lists of Defect properties and DefectViewModel properties so that I can do viewModelProperty.SetValue(viewModel, defectValue, null)?
Edit: thanks to both Jordão's and Dave's answers, I chose AutoMapper. DefectViewModel is in a WPF application, so I added the following App constructor:
public App()
{
Mapper.CreateMap<Defect, DefectViewModel>()
.ForMember("PropertyOnlyInViewModel", options => options.Ignore())
.ForMember("AnotherPropertyOnlyInViewModel", options => options.Ignore())
.ForAllMembers(memberConfigExpr =>
memberConfigExpr.Condition(resContext =>
resContext.SourceType.Equals(typeof(string)) &&
!resContext.IsSourceValueNull
)
);
}
Then, instead of all that PropertyInfo business, I just have the following line:
var defect = new Defect();
var defectViewModel = new DefectViewModel();
Mapper.Map<Defect, DefectViewModel>(defect, defectViewModel);
Take a look at AutoMapper.
There are frameworks for this, the one I know of is Automapper:
http://automapper.codeplex.com/
http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx
Replace your erroneous line with this:
PropertyInfo targetProperty = defectViewModel.GetType().GetProperty(defectProperty.Name);
targetProperty.SetValue(viewModel, defectValue, null);
Your posted code is attempting to set a Defect-tied property on a DefectViewModel object.
In terms of organizing the code, if you don't want an external library like AutoMapper, you can use a mixin-like scheme to separate the code out like this:
class Program {
static void Main(string[] args) {
var d = new Defect() { Category = "bug", Status = "open" };
var m = new DefectViewModel();
m.CopyPropertiesFrom(d);
Console.WriteLine("{0}, {1}", m.Category, m.Status);
}
}
// compositions
class Defect : MPropertyGettable {
public string Category { get; set; }
public string Status { get; set; }
// ...
}
class DefectViewModel : MPropertySettable {
public string Category { get; set; }
public string Status { get; set; }
// ...
}
// quasi-mixins
public interface MPropertyEnumerable { }
public static class PropertyEnumerable {
public static IEnumerable<string> GetProperties(this MPropertyEnumerable self) {
return self.GetType().GetProperties().Select(property => property.Name);
}
}
public interface MPropertyGettable : MPropertyEnumerable { }
public static class PropertyGettable {
public static object GetValue(this MPropertyGettable self, string name) {
return self.GetType().GetProperty(name).GetValue(self, null);
}
}
public interface MPropertySettable : MPropertyEnumerable { }
public static class PropertySettable {
public static void SetValue<T>(this MPropertySettable self, string name, T value) {
self.GetType().GetProperty(name).SetValue(self, value, null);
}
public static void CopyPropertiesFrom(this MPropertySettable self, MPropertyGettable other) {
self.GetProperties().Intersect(other.GetProperties()).ToList().ForEach(
property => self.SetValue(property, other.GetValue(property)));
}
}
This way, all the code to achieve the property-copying is separate from the classes that use it. You just need to reference the mixins in their interface list.
Note that this is not as robust or flexible as AutoMapper, because you might want to copy properties with different names or just some sub-set of the properties. Or it might downright fail if the properties don't provide the necessary getters or setters or their types differ. But, it still might be enough for your purposes.
This is cheap and easy. It makes use of System.Web.Script.Serialization and some extention methods for ease of use:
public static class JSONExts
{
public static string ToJSON(this object o)
{
var oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
return oSerializer.Serialize(o);
}
public static List<T> FromJSONToListOf<T>(this string jsonString)
{
var oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
return oSerializer.Deserialize<List<T>>(jsonString);
}
public static T FromJSONTo<T>(this string jsonString)
{
var oSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
return oSerializer.Deserialize<T>(jsonString);
}
public static T1 ConvertViaJSON<T1>(this object o)
{
return o.ToJSON().FromJSONTo<T1>();
}
}
Here's some similiar but different classes:
public class Member
{
public string Name { get; set; }
public int Age { get; set; }
public bool IsCitizen { get; set; }
public DateTime? Birthday { get; set; }
public string PetName { get; set; }
public int PetAge { get; set; }
public bool IsUgly { get; set; }
}
public class MemberV2
{
public string Name { get; set; }
public int Age { get; set; }
public bool IsCitizen { get; set; }
public DateTime? Birthday { get; set; }
public string ChildName { get; set; }
public int ChildAge { get; set; }
public bool IsCute { get; set; }
}
And here's the methods in action:
var memberClass1Obj = new Member {
Name = "Steve Smith",
Age = 25,
IsCitizen = true,
Birthday = DateTime.Now.AddYears(-30),
PetName = "Rosco",
PetAge = 4,
IsUgly = true,
};
string br = "<br /><br />";
Response.Write(memberClass1Obj.ToJSON() + br); // just to show the JSON
var memberClass2Obj = memberClass1Obj.ConvertViaJSON<MemberV2>();
Response.Write(memberClass2Obj.ToJSON()); // valid fields are filled
For one thing I would not place that code (somewhere) external but in the constructor of the ViewModel:
class DefectViewModel
{
public DefectViewModel(Defect source) { ... }
}
And if this is the only class (or one of a few) I would not automate it further but write out the property assignments. Automating it looks nice but there may be more exceptions and special cases than you expect.
Any chance you could have both classes implement an interface that defines the shared properties?

Categories

Resources