How to design an immutable object with complex initialization - c#

I'm learning about DDD, and have come across the statement that "value-objects" should be immutable. I understand that this means that the objects state should not change after it has been created. This is kind of a new way of thinking for me, but it makes sense in many cases.
Ok, so I start creating immutable value-objects.
I make sure they take the entire state as parameters to the constructor,
I don't add property setters,
and make sure no methods are allowed to modify the content (only return new instances).
But now I want to create this value object that will contain 8 different numeric values. If I create a constructor having 8 numeric parameters I feel that it will not be very easy to use, or rather - it will be easy to make a mistake when passing in the numbers. This can't be good design.
So the questions is: Are there any other ways of making my immutable object better.., any magic that can be done in C# to overcome a long parameter list in the constructor? I'm very interested in hearing your ideas..
UPDATE: Before anyone mentions it, one idea has been discussed here:
Immutable object pattern in C# - what do you think?
Would be interested in hearing other suggestions or comments though.

Use a builder:
public class Entity
{
public class Builder
{
private int _field1;
private int _field2;
private int _field3;
public Builder WithField1(int value) { _field1 = value; return this; }
public Builder WithField2(int value) { _field2 = value; return this; }
public Builder WithField3(int value) { _field3 = value; return this; }
public Entity Build() { return new Entity(_field1, _field2, _field3); }
}
private int _field1;
private int _field2;
private int _field3;
private Entity(int field1, int field2, int field3)
{
// Set the fields.
}
public int Field1 { get { return _field1; } }
public int Field2 { get { return _field2; } }
public int Field3 { get { return _field3; } }
public static Builder Build() { return new Builder(); }
}
Then create it like:
Entity myEntity = Entity.Build()
.WithField1(123)
.WithField2(456)
.WithField3(789)
.Build()
If some of the parameters are optional you won't need to call the WithXXX method and they can have default values.

At the moment, you'd have to use a constructor with lots of args, or a builder. In C# 4.0 (VS2010), you can use named/optional arguments to achieve something similar to C# 3.0 object-initializers - see here. The example on the blog is:
Person p = new Person ( forename: "Fred", surname: "Flintstone" );
But you can easily see how something similar can apply for any constructor (or other complex method). Compare to the C# 3.0 object-initializer syntax (with a mutable type):
Person p = new Person { Forename = "Fred", Surname = "Flintstone" };
Not much to tell them apart, really.
Jon Skeet has posted some thoughts on this subject too, here.

Off the top of my head, two different answers come to mind ...
... the first, and probably simplest, is to use an object factory (or builder) as a helper that ensures you get things right.
Object initialization would look like this:
var factory = new ObjectFactory();
factory.Fimble = 32;
factory.Flummix = "Nearly";
var mine = factory.CreateInstance();
... the second is to create your object as a conventional, mutable, object with a Lock() or Freeze() function. All of your mutators should check to see if the object has been locked, and throw an exception if it has.
Object initialization would look like this:
var mine = new myImmutableObject();
mine.Fimble = 32;
mine.Flummix = "Nearly";
mine.Lock(); // Now it's immutable.
Which method to take depends a lot on your context - a factory has the advantage of being convenient if you have a series of similar objects to construct, but it does introduce another class to write and maintain. A lockable object means there is only one class, but other users might get unexpected runtime errors, and testing is harder.

Although it is probably part of the domain of what you are doing, and thus my suggestion may be invalid, what about attempting to break down the 8 parameters into logical groups?
Whenever I see heaps of parameters, i feel like the object/method/contructor ought to be simpler.

I have been boggled with the same question as complex constructors is also bad design to me. I am also not a big fan of the builder concept as it seems like too much extra code to maintain. What we need is popsicle immutability, which means that an object starts out as mutable where you are allowed to use the property setters. When all properties are set there must be a way of freezing the object into an immutable state. This strategy is unfortunately not supported natively in the C# language. I therefore ended up designing my own pattern for creating immutable objects as described in this question:
Immutable object pattern in C# - what do you think?
Anders Hejlsberg is talking about support for this type of immutability from 36:30 in the following interview:
Expert to Expert: Anders Hejlsberg - The Future of C#

You can use reflection in order to initialize all the fields of the object and laziness to make "setter" like methods (using monadic functional style) in order to chain the set methods/functions together.
For example:
You can use this base class:
public class ImmutableObject<T>
{
private readonly Func<IEnumerable<KeyValuePair<string, object>>> initContainer;
protected ImmutableObject() {}
protected ImmutableObject(IEnumerable<KeyValuePair<string,object>> properties)
{
var fields = GetType().GetFields().Where(f=> f.IsPublic);
var fieldsAndValues =
from fieldInfo in fields
join keyValuePair in properties on fieldInfo.Name.ToLower() equals keyValuePair.Key.ToLower()
select new {fieldInfo, keyValuePair.Value};
fieldsAndValues.ToList().ForEach(fv=> fv.fieldInfo.SetValue(this,fv.Value));
}
protected ImmutableObject(Func<IEnumerable<KeyValuePair<string,object>>> init)
{
initContainer = init;
}
protected T setProperty(string propertyName, object propertyValue, bool lazy = true)
{
Func<IEnumerable<KeyValuePair<string, object>>> mergeFunc = delegate
{
var propertyDict = initContainer == null ? ObjectToDictonary () : initContainer();
return propertyDict.Select(p => p.Key == propertyName? new KeyValuePair<string, object>(propertyName, propertyValue) : p).ToList();
};
var containerConstructor = typeof(T).GetConstructors()
.First( ce => ce.GetParameters().Count() == 1 && ce.GetParameters()[0].ParameterType.Name == "Func`1");
return (T) (lazy ? containerConstructor.Invoke(new[] {mergeFunc}) : DictonaryToObject<T>(mergeFunc()));
}
private IEnumerable<KeyValuePair<string,object>> ObjectToDictonary()
{
var fields = GetType().GetFields().Where(f=> f.IsPublic);
return fields.Select(f=> new KeyValuePair<string,object>(f.Name, f.GetValue(this))).ToList();
}
private static object DictonaryToObject<T>(IEnumerable<KeyValuePair<string,object>> objectProperties)
{
var mainConstructor = typeof (T).GetConstructors()
.First(c => c.GetParameters().Count()== 1 && c.GetParameters().Any(p => p.ParameterType.Name == "IEnumerable`1") );
return mainConstructor.Invoke(new[]{objectProperties});
}
public T ToObject()
{
var properties = initContainer == null ? ObjectToDictonary() : initContainer();
return (T) DictonaryToObject<T>(properties);
}
}
Can be implemented like so:
public class State:ImmutableObject<State>
{
public State(){}
public State(IEnumerable<KeyValuePair<string,object>> properties):base(properties) {}
public State(Func<IEnumerable<KeyValuePair<string, object>>> func):base(func) {}
public readonly int SomeInt;
public State someInt(int someInt)
{
return setProperty("SomeInt", someInt);
}
public readonly string SomeString;
public State someString(string someString)
{
return setProperty("SomeString", someString);
}
}
and can be used like this:
//creating new empty object
var state = new State();
// Set fields, will return an empty object with the "chained methods".
var s2 = state.someInt(3).someString("a string");
// Resolves all the "chained methods" and initialize the object setting all the fields by reflection.
var s3 = s2.ToObject();

Related

the easest way of findind the difference of two objects of the same class [duplicate]

The project I'm working on needs some simple audit logging for when a user changes their email, billing address, etc. The objects we're working with are coming from different sources, one a WCF service, the other a web service.
I've implemented the following method using reflection to find changes to the properties on two different objects. This generates a list of the properties that have differences along with their old and new values.
public static IList GenerateAuditLogMessages(T originalObject, T changedObject)
{
IList list = new List();
string className = string.Concat("[", originalObject.GetType().Name, "] ");
foreach (PropertyInfo property in originalObject.GetType().GetProperties())
{
Type comparable =
property.PropertyType.GetInterface("System.IComparable");
if (comparable != null)
{
string originalPropertyValue =
property.GetValue(originalObject, null) as string;
string newPropertyValue =
property.GetValue(changedObject, null) as string;
if (originalPropertyValue != newPropertyValue)
{
list.Add(string.Concat(className, property.Name,
" changed from '", originalPropertyValue,
"' to '", newPropertyValue, "'"));
}
}
}
return list;
}
I'm looking for System.IComparable because "All numeric types (such as Int32 and Double) implement IComparable, as do String, Char, and DateTime." This seemed the best way to find any property that's not a custom class.
Tapping into the PropertyChanged event that's generated by the WCF or web service proxy code sounded good but doesn't give me enough info for my audit logs (old and new values).
Looking for input as to if there is a better way to do this, thanks!
#Aaronaught, here is some example code that is generating a positive match based on doing object.Equals:
Address address1 = new Address();
address1.StateProvince = new StateProvince();
Address address2 = new Address();
address2.StateProvince = new StateProvince();
IList list = Utility.GenerateAuditLogMessages(address1, address2);
"[Address] StateProvince changed from
'MyAccountService.StateProvince' to
'MyAccountService.StateProvince'"
It's two different instances of the StateProvince class, but the values of the properties are the same (all null in this case). We're not overriding the equals method.
IComparable is for ordering comparisons. Either use IEquatable instead, or just use the static System.Object.Equals method. The latter has the benefit of also working if the object is not a primitive type but still defines its own equality comparison by overriding Equals.
object originalValue = property.GetValue(originalObject, null);
object newValue = property.GetValue(changedObject, null);
if (!object.Equals(originalValue, newValue))
{
string originalText = (originalValue != null) ?
originalValue.ToString() : "[NULL]";
string newText = (newText != null) ?
newValue.ToString() : "[NULL]";
// etc.
}
This obviously isn't perfect, but if you're only doing it with classes that you control, then you can make sure it always works for your particular needs.
There are other methods to compare objects (such as checksums, serialization, etc.) but this is probably the most reliable if the classes don't consistently implement IPropertyChanged and you want to actually know the differences.
Update for new example code:
Address address1 = new Address();
address1.StateProvince = new StateProvince();
Address address2 = new Address();
address2.StateProvince = new StateProvince();
IList list = Utility.GenerateAuditLogMessages(address1, address2);
The reason that using object.Equals in your audit method results in a "hit" is because the instances are actually not equal!
Sure, the StateProvince may be empty in both cases, but address1 and address2 still have non-null values for the StateProvince property and each instance is different. Therefore, address1 and address2 have different properties.
Let's flip this around, take this code as an example:
Address address1 = new Address("35 Elm St");
address1.StateProvince = new StateProvince("TX");
Address address2 = new Address("35 Elm St");
address2.StateProvince = new StateProvince("AZ");
Should these be considered equal? Well, they will be, using your method, because StateProvince does not implement IComparable. That's the only reason why your method reported that the two objects were the same in the original case. Since the StateProvince class does not implement IComparable, the tracker just skips that property entirely. But these two addresses are clearly not equal!
This is why I originally suggested using object.Equals, because then you can override it in the StateProvince method to get better results:
public class StateProvince
{
public string Code { get; set; }
public override bool Equals(object obj)
{
if (obj == null)
return false;
StateProvince sp = obj as StateProvince;
if (object.ReferenceEquals(sp, null))
return false;
return (sp.Code == Code);
}
public bool Equals(StateProvince sp)
{
if (object.ReferenceEquals(sp, null))
return false;
return (sp.Code == Code);
}
public override int GetHashCode()
{
return Code.GetHashCode();
}
public override string ToString()
{
return string.Format("Code: [{0}]", Code);
}
}
Once you've done this, the object.Equals code will work perfectly. Instead of naïvely checking whether or not address1 and address2 literally have the same StateProvince reference, it will actually check for semantic equality.
The other way around this is to extend the tracking code to actually descend into sub-objects. In other words, for each property, check the Type.IsClass and optionally the Type.IsInterface property, and if true, then recursively invoke the change-tracking method on the property itself, prefixing any audit results returned recursively with the property name. So you'd end up with a change for StateProvinceCode.
I use the above approach sometimes too, but it's easier to just override Equals on the objects for which you want to compare semantic equality (i.e. audit) and provide an appropriate ToString override that makes it clear what changed. It doesn't scale for deep nesting but I think it's unusual to want to audit that way.
The last trick is to define your own interface, say IAuditable<T>, which takes a second instance of the same type as a parameter and actually returns a list (or enumerable) of all of the differences. It's similar to our overridden object.Equals method above but gives back more information. This is useful for when the object graph is really complicated and you know you can't rely on Reflection or Equals. You can combine this with the above approach; really all you have to do is substitute IComparable for your IAuditable and invoke the Audit method if it implements that interface.
This project on github checks nearly any type of property and can be customized as you need.
You might want to look at Microsoft's Testapi It has an object comparison api that does deep comparisons. It might be overkill for you but it could be worth a look.
var comparer = new ObjectComparer(new PublicPropertyObjectGraphFactory());
IEnumerable<ObjectComparisonMismatch> mismatches;
bool result = comparer.Compare(left, right, out mismatches);
foreach (var mismatch in mismatches)
{
Console.Out.WriteLine("\t'{0}' = '{1}' and '{2}'='{3}' do not match. '{4}'",
mismatch.LeftObjectNode.Name, mismatch.LeftObjectNode.ObjectValue,
mismatch.RightObjectNode.Name, mismatch.RightObjectNode.ObjectValue,
mismatch.MismatchType);
}
Here a short LINQ version that extends object and returns a list of properties that are not equal:
usage: object.DetailedCompare(objectToCompare);
public static class ObjectExtensions
{
public static List<Variance> DetailedCompare<T>(this T val1, T val2)
{
var propertyInfo = val1.GetType().GetProperties();
return propertyInfo.Select(f => new Variance
{
Property = f.Name,
ValueA = f.GetValue(val1),
ValueB = f.GetValue(val2)
})
.Where(v => !v.ValueA.Equals(v.ValueB))
.ToList();
}
public class Variance
{
public string Property { get; set; }
public object ValueA { get; set; }
public object ValueB { get; set; }
}
}
You never want to implement GetHashCode on mutable properties (properties that could be changed by someone) - i.e. non-private setters.
Imagine this scenario:
you put an instance of your object in a collection which uses GetHashCode() "under the covers" or directly (Hashtable).
Then someone changes the value of the field/property that you've used in your GetHashCode() implementation.
Guess what... your object is permanently lost in the collection since the collection uses GetHashCode() to find it! You've effectively changed the hashcode value from what was originally placed in the collection. Probably not what you wanted.
Liviu Trifoi solution: Using CompareNETObjects library.
GitHub - NuGet package - Tutorial.
I think this method is quite neat, it avoids repetition or adding anything to classes. What more are you looking for?
The only alternative would be to generate a state dictionary for the old and new objects, and write a comparison for them. The code for generating the state dictionary could reuse any serialisation you have for storing this data in the database.
The my way of Expression tree compile version. It should faster than PropertyInfo.GetValue.
static class ObjDiffCollector<T>
{
private delegate DiffEntry DiffDelegate(T x, T y);
private static readonly IReadOnlyDictionary<string, DiffDelegate> DicDiffDels;
private static PropertyInfo PropertyOf<TClass, TProperty>(Expression<Func<TClass, TProperty>> selector)
=> (PropertyInfo)((MemberExpression)selector.Body).Member;
static ObjDiffCollector()
{
var expParamX = Expression.Parameter(typeof(T), "x");
var expParamY = Expression.Parameter(typeof(T), "y");
var propDrName = PropertyOf((DiffEntry x) => x.Prop);
var propDrValX = PropertyOf((DiffEntry x) => x.ValX);
var propDrValY = PropertyOf((DiffEntry x) => x.ValY);
var dic = new Dictionary<string, DiffDelegate>();
var props = typeof(T).GetProperties();
foreach (var info in props)
{
var expValX = Expression.MakeMemberAccess(expParamX, info);
var expValY = Expression.MakeMemberAccess(expParamY, info);
var expEq = Expression.Equal(expValX, expValY);
var expNewEntry = Expression.New(typeof(DiffEntry));
var expMemberInitEntry = Expression.MemberInit(expNewEntry,
Expression.Bind(propDrName, Expression.Constant(info.Name)),
Expression.Bind(propDrValX, Expression.Convert(expValX, typeof(object))),
Expression.Bind(propDrValY, Expression.Convert(expValY, typeof(object)))
);
var expReturn = Expression.Condition(expEq
, Expression.Convert(Expression.Constant(null), typeof(DiffEntry))
, expMemberInitEntry);
var expLambda = Expression.Lambda<DiffDelegate>(expReturn, expParamX, expParamY);
var compiled = expLambda.Compile();
dic[info.Name] = compiled;
}
DicDiffDels = dic;
}
public static DiffEntry[] Diff(T x, T y)
{
var list = new List<DiffEntry>(DicDiffDels.Count);
foreach (var pair in DicDiffDels)
{
var r = pair.Value(x, y);
if (r != null) list.Add(r);
}
return list.ToArray();
}
}
class DiffEntry
{
public string Prop { get; set; }
public object ValX { get; set; }
public object ValY { get; set; }
}

What is the best way to implement a Rust enum in C#?

I have an entity that can be in one of different states (StateA, StateB and StateC), and in each of them have relevant data of distinct types (TStateA, TStateB, TStateC). Enums in Rust represent this perfectly. What is the best way to implement something like this in C#?
This question may appear similar, but enums in Rust and unions in C are significantly different.
You need a class to represent your Entity
class Entity {States state;}
Then you need a set of classes to represent your states.
abstract class States {
// maybe something in common
}
class StateA : MyState {
// StateA's data and methods
}
class StateB : MyState {
// ...
}
Then you need to write code like
StateA maybeStateA = _state as StateA;
If (maybeStateA != null)
{
- do something with the data in maybeStateA
}
C# does not have a nice way of writing code for this yet, maybe the Pattern Matching that is being considered for C#.next would help.
I think you should rethink your design to use object relationships and containment, trying to take a design that works in rust and force it into C# may not be the best option.
This might be crazy, but if you are hard-up about emulating Rust-like enums in C#, you could do it with some generics. Bonus: you keep type-safety and also get Intellisense out of the deal! You'll lose a little flexibility with various value types, but I think the safety is probably worth the inconvenience.
enum Option
{
Some,
None
}
class RustyEnum<TType, TValue>
{
public TType EnumType { get; set; }
public TValue EnumValue { get; set; }
}
// This static class basically gives you type-inference when creating items. Sugar!
static class RustyEnum
{
// Will leave the value as a null `object`. Not sure if this is actually useful.
public static RustyEnum<TType, object> Create<TType>(TType e)
{
return new RustyEnum<TType, object>
{
EnumType = e,
EnumValue = null
};
}
// Will let you set the value also
public static RustyEnum<TType, TValue> Create<TType, TValue>(TType e, TValue v)
{
return new RustyEnum<TType, TValue>
{
EnumType = e,
EnumValue = v
};
}
}
void Main()
{
var hasSome = RustyEnum.Create(Option.Some, 42);
var hasNone = RustyEnum.Create(Option.None, 0);
UseTheEnum(hasSome);
UseTheEnum(hasNone);
}
void UseTheEnum(RustyEnum<Option, int> item)
{
switch (item.EnumType)
{
case Option.Some:
Debug.WriteLine("Wow, the value is {0}!", item.EnumValue);
break;
default:
Debug.WriteLine("You know nuffin', Jon Snow!");
break;
}
}
Here's another sample demonstrating the use of a custom reference type.
class MyComplexValue
{
public int A { get; set; }
public int B { get; set; }
public int C { get; set; }
public override string ToString()
{
return string.Format("A: {0}, B: {1}, C: {2}", A, B, C);
}
}
void Main()
{
var hasSome = RustyEnum.Create(Option.Some, new MyComplexValue { A = 1, B = 2, C = 3});
var hasNone = RustyEnum.Create(Option.None, null as MyComplexValue);
UseTheEnum(hasSome);
UseTheEnum(hasNone);
}
void UseTheEnum(RustyEnum<Option, MyComplexValue> item)
{
switch (item.EnumType)
{
case Option.Some:
Debug.WriteLine("Wow, the value is {0}!", item.EnumValue);
break;
default:
Debug.WriteLine("You know nuffin', Jon Snow!");
break;
}
}
This looks a lot like Abstract Data Types in functional languages. There's no direct support for this in C#, but you can use one abstract class for the data type plus one sealed class for each data constructor.
abstract class MyState {
// maybe something in common
}
sealed class StateA : MyState {
// StateA's data and methods
}
sealed class StateB : MyState {
// ...
}
Of course, there's nothing prohibiting you from adding a StateZ : MyState class later, and the compiler won't warn you that your functions are not exhaustive.
Just from the back of my head, as a quick implementation...
I would first declare the Enum type and define enumerate items normally.
enum MyEnum{
[MyType('MyCustomIntType')]
Item1,
[MyType('MyCustomOtherType')]
Item2,
}
Now I define the Attribute type MyTypeAttribute with a property called TypeString.
Next, I need to write an extension method to extract the Type for each enum item (first in string, then later reflect to real type):
public static string GetMyType(this Enum eValue){
var _nAttributes = eValue.GetType().GetField(eValue.ToString()).GetCustomAttributes(typeof (MyTypeAttribute), false);
// handle other stuff if necessary
return ((MyTypeAttribute) _nAttributes.First()).TypeString;
}
Finally, get the real type using reflection...
I think the upside of this approach is easy to use later in the code:
var item = MyEnum.SomeItem;
var itemType = GetType(item.GetMyType());
I've been looking into Rust recently and been thinking the same questions. The real problem is the absence of the Rust deconstruction pattern matching but the type itself is long-winded but relatively straightforward if you are willing to use boxing:
// You need a new type with a lot of boilerplate for every
// Rust-like enum but they can all be implemented as a struct
// containing an enum discriminator and an object value.
// The struct is small and can be passed by value
public struct RustyEnum
{
// discriminator type must be public so we can do a switch because there is no equivalent to Rust deconstructor
public enum DiscriminatorType
{
// The 0 value doesn't have to be None
// but it must be something that has a reasonable default value
// because this is a struct.
// If it has a struct type value then the access method
// must check for Value == null
None=0,
IVal,
SVal,
CVal,
}
// a discriminator for users to switch on
public DiscriminatorType Discriminator {get;private set;}
// Value is reference or box so no generics needed
private object Value;
// ctor is private so you can't create an invalid instance
private RustyEnum(DiscriminatorType type, object value)
{
Discriminator = type;
Value = value;
}
// union access methods one for each enum member with a value
public int GetIVal() { return (int)Value; }
public string GetSVal() { return (string)Value; }
public C GetCVal() { return (C)Value; }
// traditional enum members become static readonly instances
public static readonly RustyEnum None = new RustyEnum(DiscriminatorType.None,null);
// Rusty enum members that have values become static factory methods
public static RustyEnum FromIVal(int i)
{
return new RustyEnum(DiscriminatorType.IVal,i);
}
//....etc
}
Usage is then:
var x = RustyEnum::FromSVal("hello");
switch(x.Discriminator)
{
case RustyEnum::DiscriminatorType::None:
break;
case RustyEnum::DiscriminatorType::SVal:
string s = x.GetSVal();
break;
case RustyEnum::DiscriminatorType::IVal:
int i = x.GetIVal();
break;
}
If you add some extra public const fields this could be reduced to
var x = RustyEnum::FromSVal("hello");
switch(x.Discriminator)
{
case RustyEnum::None:
break;
case RustyEnum::SVal:
string s = x.GetSVal();
break;
case RustyEnum::IVal:
int i = x.GetIVal();
break;
}
... but you then need a different name for creating the valueless members (like None in this example)
It seems to me that if the C# compiler was to implement rust enums without changing the CLR then this is the sort of code that it would generate.
It would be easy enough to create a .ttinclude to generate this.
Deconstruction is not as nice as Rust match but there is no alternative that is both efficient and idiot proof (the inefficient way is to use something like
x.IfSVal(sval=> {....})
To summarize my rambling - It can be done but it's unlikely to be worth the effort.
Short answer you can't. Even if you feel you can just don't do it you would shoot yourself in foot in doing so. We'll have to wait for the C# team to come up with a type with something like below
struct lives on stack in most cases this means it has a fixed size in memory
What we are expecting is sort of multiple struct with different layout but still fits in one decided stack of memory. The way rust handles this is by using the memory size of largest of the group for example
# Right now:
struct A { int a } # 4 bytes
struct B { int a, int b } # 8 bytes
# Can do but highly don't recommend would be waste of precious time, memory and cpu
struct AB {
A a,
B b
} # 12 bytes + 2 bytes to keep bool to check which struct should be used in code
# Future/Should be
super struct AB {
A(int),
B(int, int)
} # 8 bytes
Never did anything in Rust, but looking at the docs it seams to me that you would have to implement a textbook C# class. Since Rust enums even support functions and implementations of various types.
Probabily an abstract class.

Get and set value from bindinglist<T> with coordinates c#

I'm having trouble getting and setting the values of an item in a bindinglist with coordinates when the type vary.
For example, let's say I have three classes:
public class Client{
public string Name{ get; set; }
}
public class Debt{
public string AccountType{ get; set; }
public int DebtValue { get; set; }
}
public class Accounts{
public string Owner{ get; set; }
public int AccountNumber { get; set; }
public bool IsChekingAccount { get; set; }
}
and then, three bindinglists (imagine they are populated):
public BindingList<Client> listOne;
public BindingList<Debt> listTwo;
public BindingList<Accounts> listThree;
I'm trying to create an extension method that returns an Object with the value requested, or sets the value if it is provided.
public static Object GetValueByCoordinates(this IBindingList list, int x, int y) { /*some magic*/ }
public static Object SetValueByCoordinates(this IBindingList list, int x, int y, Object value) { /*some other magic*/ }
So, for instance, I need to be able to set the value of the item (2,3) in the listThree, and the value (1,1) in listTwo:
listThree.SetValueByCoordinates(2,3,false);
listThree.SetValueByCoordinates(1,1,"My self");
or get the value (1,1) and (2,2) from listOne and listTwo:
string result = listOne.GetValueByCoordinates(1,1).ToString();
intresult = Convert.ToInt32(listOne.GetValueByCoordinates(1,1));
How would you achieve such behavior? i was thinking of using reflection, but I know little to nothing about it.
please note that the methods MUST be called that way, so using something like this must be avoided
public static Object GetValueByCoordinates<T>(this BindingList<T> list, int x, int y) { /*some magic*/ }
Any help will be appreciated.
As mentioned, I am very skeptical that the approach you're asking for help with is likely to be the best or most appropriate way to address whatever the broader issue you're trying to solve is. It can be done (and without very much difficulty), but the resulting code is difficult to maintain, error-prone, and not very readable (which leads to the first two problems).
That said, there are lots of different ways to implement the specific behavior you're asking for. And even if this is not the best way to solve your current problem, the basic techniques are useful to know for other types of problems. With that in mind, here are two of the most obvious ways you might address your problem.
Manually configure a mapping from indexes to getters and setters:
IMHO this is the most preferable way. Not because it's elegant or easy to extend, but specifically because it's not either of those things. Requiring code maintainers to explicitly create the data structure elements to support each type and property that you want to handle will discourage a proliferation of this technique for other related problems, and even for the current problem. It could even encourage someone to spend a little more time thinking about the broader problem so as to find a better strategy.
This approach does have the advantage that it is reasonably performant. Because the code is generated at compile time, the only real overhead is the boxing that occurs for value types. There's some casting but for the reference types that overhead should be practically unmeasurable, and even the boxing overhead may not show up on a profile, depending on how intensively this code might be used.
This particular solution looks like this:
static class ManualIndexedProperty
{
public static void SetValueByCoordinates(this IBindingList list, int x, int y, object value)
{
object o = list[x];
_typeToSetter[o.GetType()][y](o, value);
}
public static object GetValueByCoordinates(this IBindingList list, int x, int y)
{
object o = list[x];
return _typeToGetter[o.GetType()][y](o);
}
private static readonly Dictionary<Type, Func<object, object>[]> _typeToGetter =
new Dictionary<Type, Func<object, object>[]>()
{
{
typeof(Client),
new Func<object, object>[]
{
o => ((Client)o).Name
}
},
{
typeof(Debt),
new Func<object, object>[]
{
o => ((Debt)o).AccountType,
o => ((Debt)o).DebtValue,
}
},
{
typeof(Accounts),
new Func<object, object>[]
{
o => ((Accounts)o).Owner,
o => ((Accounts)o).AccountNumber,
o => ((Accounts)o).IsChekingAccount,
}
},
};
private static readonly Dictionary<Type, Action<object, object>[]> _typeToSetter =
new Dictionary<Type, Action<object, object>[]>()
{
{
typeof(Client),
new Action<object, object>[]
{
(o1, o2) => ((Client)o1).Name = (string)o2
}
},
{
typeof(Debt),
new Action<object, object>[]
{
(o1, o2) => ((Debt)o1).AccountType = (string)o2,
(o1, o2) => ((Debt)o1).DebtValue = (int)o2,
}
},
{
typeof(Accounts),
new Action<object, object>[]
{
(o1, o2) => ((Accounts)o1).Owner = (string)o2,
(o1, o2) => ((Accounts)o1).AccountNumber = (int)o2,
(o1, o2) => ((Accounts)o1).IsChekingAccount = (bool)o2,
}
},
};
}
Two dictionaries are declared, one each for setting and getting property values. The dictionaries map the element object's type to an array of delegate instances to perform the actual work. Each delegate instance references an anonymous method which has been hand-coded to perform the necessary operation.
One major advantage to this approach is that it is explicit and obvious what index corresponds to what property for each type.
This approach will be tedious and time-consuming to set up if you are dealing with any significant number of types and/or properties. But IMHO that's a good thing. As I noted above, hopefully the pain of this approach can help convince someone to abandon the idea of accessing the properties by index altogether. :)
If this kind of tedium is unacceptable and yet you still insist on the indexed-property-access approach, then you can in fact use reflection as an alternative…
Use reflection to access the properties:
This technique is more dynamic. Once implemented, it works for any type object without modification, and does not require additional work to support new types.
One major disadvantage is that in order to produce consistent, predictable results, it sorts the properties by name. This ensures that changes in the C# compiler and/or CLR won't break the code, but it means you can't add or remove properties from a type without updating the code that is accessing those properties by index.
In my demo usage code (see further below), I address this maintenance issue by declaring enum types that provide int values for property names. This would be a good way to help reduce the maintenance overhead if the code is actually referring to the properties with literal index values.
However, it's possible your scenario involves dynamically accessing the property values by index, e.g. in a serialization scenario or similar. In that case, you will also need to add something that can remap or otherwise deal with changes in the index values should properties be added or removed to the types.
Frankly, either way this issue of the types indexes changing is one big reason I'd strongly recommend against this indexed access to properties in the first place. But again, if you insist…
static class ReflectionIndexedProperty
{
public static void SetValueByCoordinates(this IBindingList list, int x, int y, object value)
{
object o = list[x];
GetProperty(o, y).SetValue(o, value);
}
public static object GetValueByCoordinates(this IBindingList list, int x, int y)
{
object o = list[x];
return GetProperty(o, y).GetValue(o);
}
private static PropertyInfo GetProperty(object o, int index)
{
Type type = o.GetType();
PropertyInfo[] properties;
if (!_typeToProperty.TryGetValue(type, out properties))
{
properties = type.GetProperties();
Array.Sort(properties, (p1, p2) => string.Compare(p1.Name, p2.Name, StringComparison.OrdinalIgnoreCase));
_typeToProperty[type] = properties;
}
return properties[index];
}
private static readonly Dictionary<Type, PropertyInfo[]> _typeToProperty = new Dictionary<Type, PropertyInfo[]>();
}
In this version, the code retrieves the array of PropertyInfo objects for a given type, sorts that array by name, retrieves the appropriate PropertyInfo object for the given index, and then uses that PropertyInfo object to set or get the property value, as appropriate.
Reflection incurs a significant run-time performance overhead. This particular implementation mitigates some of that overhead by caching the sorted arrays of PropertyInfo objects. That way, they only need to be created once, the first time the code has to handle an object of the given type.
Demo code:
As I mentioned, to make it easier to compare the two approaches without having to go to each method call and hand-change an integer literal used for the call, I created some simple enum types to represent the property indexes. I also wrote some code to initialize some lists that could be tested.
Note: one very important thing to point out is that in your question you were not very consistent about how you were indexing the properties. In my code example, I have chose to stick with a 0-based index (consistent with the natural indexing used in C# arrays and other collections). You can of course use a different base (e.g. 1-based indexing), but you will need to make sure you are entirely consistent throughout the code (including subtracting 1 from the passed-in index when actually indexing an array).
My demo code looks like this:
class Program
{
static void Main(string[] args)
{
BindingList<Client> listOne = new BindingList<Client>()
{
new Client { Name = "ClientName1" },
new Client { Name = "ClientName2" },
new Client { Name = "ClientName3" },
};
BindingList<Debt> listTwo = new BindingList<Debt>()
{
new Debt { AccountType = "AccountType1", DebtValue = 29 },
new Debt { AccountType = "AccountType2", DebtValue = 31 },
new Debt { AccountType = "AccountType3", DebtValue = 37 },
};
BindingList<Accounts> listThree = new BindingList<Accounts>()
{
new Accounts { Owner = "Owner1", AccountNumber = 17, IsChekingAccount = false },
new Accounts { Owner = "Owner2", AccountNumber = 19, IsChekingAccount = true },
new Accounts { Owner = "Owner3", AccountNumber = 23, IsChekingAccount = true },
};
LogList(listThree);
listThree.SetValueByCoordinates(2, (int)AccountsProperty.IsChekingAccount, false);
listThree.SetValueByCoordinates(1, (int)AccountsProperty.Owner, "My self");
LogList(listThree);
string result1 = (string)listOne.GetValueByCoordinates(0, (int)ClientProperty.Name);
int result2 = (int)listTwo.GetValueByCoordinates(1, (int)DebtProperty.DebtValue);
LogList(listOne);
LogList(listTwo);
Console.WriteLine("result1: " + result1);
Console.WriteLine("result2: " + result2);
}
static void LogList<T>(BindingList<T> list)
{
foreach (T t in list)
{
Console.WriteLine(t);
}
Console.WriteLine();
}
}
Note that I use simple casting to convert from object to the specific type, both with setting property values and getting them. This is a much better approach than e.g. calling ToString() or Convert.ToInt32(); you know exactly what the type is supposed to be, and it's either an actual instance of that type (for reference types) or a boxed instance (for value types), and either way a cast does exactly what you need.
I also added ToString() overrides to your example classes to make it easier to see the output:
public class Client
{
public string Name { get; set; }
public override string ToString()
{
return "{" + Name + "}";
}
}
public class Debt
{
public string AccountType { get; set; }
public int DebtValue { get; set; }
public override string ToString()
{
return "{" + AccountType + ", " + DebtValue + "}";
}
}
public class Accounts
{
public string Owner { get; set; }
public int AccountNumber { get; set; }
public bool IsChekingAccount { get; set; }
public override string ToString()
{
return "{" + Owner + ", " + AccountNumber + ", " + IsChekingAccount + "}";
}
}
Finally, here are the enum declarations used:
Manual indexing:
enum ClientProperty
{
Name = 0
}
enum DebtProperty
{
AccountType = 0,
DebtValue = 1
}
enum AccountsProperty
{
Owner = 0,
AccountNumber = 1,
IsChekingAccount = 2,
}
Reflection/sorted by name:
enum ClientProperty
{
Name = 0
}
enum DebtProperty
{
AccountType = 0,
DebtValue = 1
}
enum AccountsProperty
{
AccountNumber = 0,
IsChekingAccount = 1,
Owner = 2,
}
Of course, these could both have been the same values. That is, while you don't have control over the sort order, once the property names are given, the manual version could have declared the manually-written lambdas in sorted-by-name order so that the same indexes would have worked either way. It doesn't matter too much what you decide to do; it just has to be consistent.
Final thoughts…
Have I mentioned yet how strongly I would recommend against building any significant amount of code around this technique? It's not at all clear what your actual bigger-picture problem you're trying to solve is, but there are just a lot of different ways for this to go wrong, and it is likely to lead to lots of hard-to-find, time-consuming-to-fix bugs in the code.
In terms of performance, the above should not be too bad as long as you are not executing the code in a tight loop for huge numbers of objects and property values. The manual (first) example in particular should be relatively fast. It is possible to achieve the generalized design of the reflection-based approach with the minimal overhead of the manual approach by using the Expression type. That's a bit more complicated, but would have the advantage that you can generate expressions dynamically that wind up being effectively the compiled-code implementation of the manual approach.

List of Anonymous objects?

I have a class using the List class. When attempting to set up the Add function to add my anonymous type, all I get is errors.
I've been searching for hours and as best I can tell, every example I've seen is doing the same thing. So I don't understand what's wrong.
class fileHistory<Object> : List<Object>
{
public new void Add(DateTime ts, int st)
{
base.Add( new { timeStamp = ts; status = st;} );
}
}
You don't need a generic declaration in your class definition, and you also need to change semicolons to commas:
public class fileHistory : List<Object>
{
public new void Add(DateTime ts, int st)
{
base.Add( new { timeStamp = ts, status = st} );
}
}
Right, you can overwrite (not polymorphism! check I used the word overwrite instead of override) List<T>.Add(T) method, but I believe that you could solve your issue using composition instead of inheritance and your code will work flawlessly:
class fileHistory
{
private readonly List<object> _log = new List<object>();
public void Add(DateTime ts, int st)
{
_log.Add( new { timeStamp = ts; status = st;} );
}
}
BTW, I see three design flaws here:
Anonymous types aren't meant to your use case. If you are adding objects with these two properties and you do it in a concrete use case like yours, maybe you're using anonymous types because of your laziness of designing a class with 2 properties??? ;)
Because of #1, why you would create a list of objects using a generic list? It defeats the entire purpose of generics!!
I find a bad design decision hidding Add of List<T>. Use composition instead of inheritance in these cases. Also, I don't know why you're using identifier re-using with new keyword when C# supports method overloading. In List<T> there's no overload of Add with your input parameters...
My advise is: code isn't fancier because of using fancy syntactic sugar provided by C#. Sometimes you don't need it, and honestly, I believe this is the case.
For those who're worried about LINQ...
Any class might or might not implement IEnumerable<T>. The whole fileHistory class can be iterated with foreach or LINQ and its extension methods implementing IEnumerable<T>:
// Check that I dropped the lazy approach of using
// anonymous types!!
class fileHistory : IEnumerable<FileLog>
{
private readonly List<FileLog> _log = new List<FileLog>();
public IEnumerator<FileLog> GetEnumerator()
{
return _log.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _log.GetEnumerator();
}
public void Add(DateTime ts, int st)
{
_log.Add(new FileLog { timeStamp = ts; status = st;} );
}
}
...and now some class like this can be iterated even when using composition instead of inheritance:
new fileHistory().Where(log => log.DateTime < DateTime.Now);
class fileHistory<Object> : List<Object>
{
public new void Add(DateTime ts, int st)
{
// That's how it's supposed to be
base.Add(new { timeStamp = ts, status = st });
}
}
Hope I've helped!

c# copy constructor generator

I want to copy values from one object to another object. Something similar to pass by value but with assignment.
For example:
PushPin newValPushPin = oldPushPin; //I want to break the reference here.
I was told to write a copy constructor for this. But this class has a lot of properties, it will probably take an hour to write a copy constructor by hand.
Is there a better way to assign an object to another object by value?
If not, is there a copy constructor generator?
Note: ICloneable is not available in Silverlight.
If you can mark the object that is to be cloned as Serializable then you can use in-memory serialization to create a copy. Check the following code, it has the advantage that it will work on other kinds of objects as well and that you don't have to change your copy constructor or copy code each time an property is added, removed or changed:
class Program
{
static void Main(string[] args)
{
var foo = new Foo(10, "test", new Bar("Detail 1"), new Bar("Detail 2"));
var clonedFoo = foo.Clone();
Console.WriteLine("Id {0} Bar count {1}", clonedFoo.Id, clonedFoo.Bars.Count());
}
}
public static class ClonerExtensions
{
public static TObject Clone<TObject>(this TObject toClone)
{
var formatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream())
{
formatter.Serialize(memoryStream, toClone);
memoryStream.Position = 0;
return (TObject) formatter.Deserialize(memoryStream);
}
}
}
[Serializable]
public class Foo
{
public int Id { get; private set; }
public string Name { get; private set; }
public IEnumerable<Bar> Bars { get; private set; }
public Foo(int id, string name, params Bar[] bars)
{
Id = id;
Name = name;
Bars = bars;
}
}
[Serializable]
public class Bar
{
public string Detail { get; private set; }
public Bar(string detail)
{
Detail = detail;
}
}
There is a protected member called "MemberwiseClone", you can write this in your class...
public MyClass Clone(){
return (MyClass)this.MemberwiseClone();
}
then you can access..
MyClass newObject = oldObject.Clone();
The only way (that I'm aware of) to do this, and do it correctly, is to implement the copy yourself. Take for example:
public class FrobAndState
{
public Frob Frobber { get; set;}
public bool State { get; set; }
}
public class Frob
{
public List<int> Values { get; private set; }
public Frob(int[] values)
{
Values = new List<int>(values);
}
}
In this example you'd need to know how Frob was implemented, i.e. the fact that you need to call the constructor to create a copy of it as Values is read-only, to be able to make a copy of a given instance of FrobAndState.
Also - you couldn't just implement FrobAndState.Copy thusly:
public class FrobAndState
{
// ... Properties
public FrobAndState Copy()
{
var new = new FrobAndState();
new.State = this.State;
new.Frobber = this.Frobber;
}
}
Because both the instance of FrobAndState that you called .Copy() on, and the new instance would both have a reference to the same instance of Frobber.
In short, copying things is hard and any Copy implementation is difficult to get right.
C# does not have a copy constructor. There are different ways to tackle this. At the OOP level you could use inheritance or aggregation. AutoMapper might also be worth a try.
I want to copy values from one object
to another object. Something similiar
to pass by value but with assignment.
What do you mean by "with assignment"? If you mean that you want people to be able to say:
a = b;
And for you to define what = means, the only way you can do that in C# is if b is a different type to a and you've defined an implicit conversion (or more tenuously, if a stands for something of the form x.Y where Y is a property with a setter). You can't override = for a simple assignment between identical types in C#.
I was told to write a copy constructor
for this. But this class has alot of
properties, it will probably take an
hour to write a copy constructor by
hand.
If that's really true, then I would guess that you have a different problem. Your class is too big.
If you make your class Serializable you could Serialize it to a MemoryStream and Deserialize to a new instance.
If you want copy-on-assignment you should be using a struct instead of a class. But be careful, it is easy to make subtle mistakes. It is highly recommended that all stucts be immmutable to reduce the chance for error.
Though, this may not answer your question directly, but to add a cent; usually the term Clone is linked with shallow copy(referenced objects). To have a deep copy, I believe you will need to look into the some creational pattern(prototype?). The answer to this question might help.
You implement Justin Angel's method of cloning objects in Silverlight
using System;
using System.Reflection;
using System.Windows;
namespace JustinAngelNet.Silverlight.Framework
{
public static class SilverlightExtensions
{
public static T Clone<T>(T source)
{
T cloned = (T) Activator.CreateInstance(source.GetType());
foreach (PropertyInfo curPropInfo in source.GetType().GetProperties())
{
if (curPropInfo.GetGetMethod() != null
&& (curPropInfo.GetSetMethod() != null))
{
// Handle Non-indexer properties
if (curPropInfo.Name != "Item")
{
// get property from source
object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {});
// clone if needed
if (getValue != null && getValue is DependencyObject)
getValue = Clone((DependencyObject) getValue);
// set property on cloned
if (getValue != null)
curPropInfo.GetSetMethod().Invoke(cloned, new object[] {getValue});
}
// handle indexer
else
{
// get count for indexer
int numberofItemInColleciton =
(int)
curPropInfo.ReflectedType.GetProperty("Count").GetGetMethod().Invoke(source, new object[] {});
// run on indexer
for (int i = 0; i < numberofItemInColleciton; i++)
{
// get item through Indexer
object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {i});
// clone if needed
if (getValue != null && getValue is DependencyObject)
getValue = Clone((DependencyObject) getValue);
// add item to collection
curPropInfo.ReflectedType.GetMethod("Add").Invoke(cloned, new object[] {getValue});
}
}
}
}
return cloned;
}
}
}
Then you can do this
MyClass newObject = SilverlightExtensions.Clone(oldObject);

Categories

Resources