Immutable builder and updaterImmutable Queue in Java using an Immutable StackBloch's Builder Pattern / UpdaterInitializing immutable objects with a nested builderAlternative to the Josh Bloch Builder pattern in C#Generic immutable object builderReally simple immutable classSelective updates to immutable typesImmutable type updater using a special constructor

How to gently end involvement with an online community?

Justifying the use of directed energy weapons

Why doesn't 'd /= d' throw a division by zero exception?

Is using a hyperlink to close a modal a poor design decision?

How should I face my manager if I make a mistake because a senior coworker explained something incorrectly to me?

Why in most German places is the church the tallest building?

Is immersion of utensils (tevila) valid before koshering (hagala)?

Algorithms vs LP or MIP

Does travel insurance for short flight delays exist?

Thank God it's Friday, tomorrow is THE weekend. Why the definite article?

Do they have Supervillain(s)?

Ensuring all network services on a device use strong TLS cipher suites

“T” in subscript in formulas

Is there any music source code for sound chips?

Architectural feasibility of a tiered circular stone keep

Does norwegian.no airline overbook flights?

Is a player able to change alignment midway through an adventure?

Antonym of "billable"

Would it be possible to have a GMO that produces chocolate?

What do these triangles above and below the staff mean?

Prove your innocence

Understanding Parallelize methods

What is this symbol: semicircles facing each other?

Anatomically Correct Whomping Willow



Immutable builder and updater


Immutable Queue in Java using an Immutable StackBloch's Builder Pattern / UpdaterInitializing immutable objects with a nested builderAlternative to the Josh Bloch Builder pattern in C#Generic immutable object builderReally simple immutable classSelective updates to immutable typesImmutable type updater using a special constructor






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








8












$begingroup$


There aren't enough questions about creating immutable objects... so why not try it again with another approach. This time, it's a builder that maps properties to constructor parameters. Properties are selected via the With method that also expects a new value for the parameter. Constructor parameters must match properties so it's primarily for DTOs that follow this pattern. Build tries to find that constructor and creates the object.



// I need this primarily for the left-join of optional parameters.
internal class IgnoreCase : IEquatable<string>

public string Value get; set;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase Value = value ;


public class ImmutableBuilder<T>

private readonly IList<(MemberExpression Selector, object Value)> _selectors = new List<(MemberExpression Selector, object Value)>();

public ImmutableBuilder<T> With<TProperty>(Expression<Func<T, TProperty>> selector, TProperty value)

_selectors.Add(((MemberExpression)selector.Body, value));
return this;


public T Build()

var ctors =
from ctor in typeof(T).GetConstructors()
let parameters = ctor.GetParameters()
// Join parameters and values by parameter order.
// The ctor requires them sorted but they might be initialized in any order.
let requiredParameterValues =
from parameter in parameters.Where(p => !p.IsOptional)
join selector in _selectors on (IgnoreCase)parameter.Name equals (IgnoreCase)selector.Selector.Member.Name
select selector.Value
// Get optional parameters if any.
let optionalParameterValues =
from parameter in parameters.Where(p => p.IsOptional)
join selector in _selectors on (IgnoreCase)parameter.Name equals (IgnoreCase)selector.Selector.Member.Name into s
from selector in s.DefaultIfEmpty()
select selector.Value
// Make sure all required parameters are specified.
where requiredParameterValues.Count() == parameters.Where(p => !p.IsOptional).Count()
select (ctor, requiredParameterValues, optionalParameterValues);

var theOne = ctors.Single();
return (T)theOne.ctor.Invoke(theOne.requiredParameterValues.Concat(theOne.optionalParameterValues).ToArray());



public static class Immutable<T>

public static ImmutableBuilder<T> Builder => new ImmutableBuilder<T>();



In case we already have an immutable type and want to modify it by changing just some values, the ImmutableHelper can be used. It also provides the With method expecting a new value. Then matches it and other properties with the constructor and uses origianl values as defaults and for the specified property the new value.



public static class ImmutableHelper

public static T With<T, TProperty>(this T obj, Expression<Func<T, TProperty>> selector, TProperty value)

var comparer = StringComparer.OrdinalIgnoreCase;

var propertyName = ((MemberExpression)selector.Body).Member.Name;
var properties = typeof(T).GetProperties();

var propertyNames =
properties
.Select(x => x.Name)
// A hash-set is convenient for name matching in the next step.
.ToImmutableHashSet(comparer);

// Find the constructor that matches property names.
var ctors =
from ctor in typeof(T).GetConstructors()
where propertyNames.IsProperSupersetOf(ctor.GetParameters().Select(x => x.Name))
select ctor;

var theOne = ctors.Single(); // There can be only one match.

var parameters =
from parameter in theOne.GetParameters()
join property in properties on (IgnoreCase)parameter.Name equals (IgnoreCase)property.Name
// They definitely match so no comparer is necessary.
// Use either the new value or the current one.
select property.Name == propertyName ? value : property.GetValue(obj);

return (T)theOne.Invoke(parameters.ToArray());




Example



This is how it can be used:



void Main()

var person =
Immutable<Person>
.Builder
.With(x => x.FirstName, "Jane")
.With(x => x.LastName, null)
//.With(x => x.NickName, "JD") // Optional
.Build();

person.With(x => x.LastName, "Doe").Dump();


public class Person

public Person(string firstName, string lastName, string nickName = null)

FirstName = firstName;
LastName = lastName;
NickName = nickName;


// This ctor should confuse the API.
public Person(string other)

public string FirstName get;

public string LastName get;

public string NickName get;

// This property should confuse the API too.
public string FullName => $"LastName, FirstName";




What do you say? Crazy? Insane? I like it? Let's improve it?










share|improve this question











$endgroup$









  • 2




    $begingroup$
    This has a use case for building controllers and what not that have dozens of parameters. Does this also work with optional ctr arguments?
    $endgroup$
    – dfhwze
    9 hours ago






  • 1




    $begingroup$
    @dfhwze it doesn't... but it definitelly could... and should.
    $endgroup$
    – t3chb0t
    9 hours ago










  • $begingroup$
    Ok ... so let's improve it! :p
    $endgroup$
    – dfhwze
    9 hours ago










  • $begingroup$
    @dfhwze done! ;-] at least the main builder can do this now.
    $endgroup$
    – t3chb0t
    9 hours ago







  • 1




    $begingroup$
    I like the With extensions method that helps to create modified copies of mutable types. However I didn't get the use case of the ImmutableBuilder.. Why not just calling the constructor?
    $endgroup$
    – JanDotNet
    6 hours ago

















8












$begingroup$


There aren't enough questions about creating immutable objects... so why not try it again with another approach. This time, it's a builder that maps properties to constructor parameters. Properties are selected via the With method that also expects a new value for the parameter. Constructor parameters must match properties so it's primarily for DTOs that follow this pattern. Build tries to find that constructor and creates the object.



// I need this primarily for the left-join of optional parameters.
internal class IgnoreCase : IEquatable<string>

public string Value get; set;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase Value = value ;


public class ImmutableBuilder<T>

private readonly IList<(MemberExpression Selector, object Value)> _selectors = new List<(MemberExpression Selector, object Value)>();

public ImmutableBuilder<T> With<TProperty>(Expression<Func<T, TProperty>> selector, TProperty value)

_selectors.Add(((MemberExpression)selector.Body, value));
return this;


public T Build()

var ctors =
from ctor in typeof(T).GetConstructors()
let parameters = ctor.GetParameters()
// Join parameters and values by parameter order.
// The ctor requires them sorted but they might be initialized in any order.
let requiredParameterValues =
from parameter in parameters.Where(p => !p.IsOptional)
join selector in _selectors on (IgnoreCase)parameter.Name equals (IgnoreCase)selector.Selector.Member.Name
select selector.Value
// Get optional parameters if any.
let optionalParameterValues =
from parameter in parameters.Where(p => p.IsOptional)
join selector in _selectors on (IgnoreCase)parameter.Name equals (IgnoreCase)selector.Selector.Member.Name into s
from selector in s.DefaultIfEmpty()
select selector.Value
// Make sure all required parameters are specified.
where requiredParameterValues.Count() == parameters.Where(p => !p.IsOptional).Count()
select (ctor, requiredParameterValues, optionalParameterValues);

var theOne = ctors.Single();
return (T)theOne.ctor.Invoke(theOne.requiredParameterValues.Concat(theOne.optionalParameterValues).ToArray());



public static class Immutable<T>

public static ImmutableBuilder<T> Builder => new ImmutableBuilder<T>();



In case we already have an immutable type and want to modify it by changing just some values, the ImmutableHelper can be used. It also provides the With method expecting a new value. Then matches it and other properties with the constructor and uses origianl values as defaults and for the specified property the new value.



public static class ImmutableHelper

public static T With<T, TProperty>(this T obj, Expression<Func<T, TProperty>> selector, TProperty value)

var comparer = StringComparer.OrdinalIgnoreCase;

var propertyName = ((MemberExpression)selector.Body).Member.Name;
var properties = typeof(T).GetProperties();

var propertyNames =
properties
.Select(x => x.Name)
// A hash-set is convenient for name matching in the next step.
.ToImmutableHashSet(comparer);

// Find the constructor that matches property names.
var ctors =
from ctor in typeof(T).GetConstructors()
where propertyNames.IsProperSupersetOf(ctor.GetParameters().Select(x => x.Name))
select ctor;

var theOne = ctors.Single(); // There can be only one match.

var parameters =
from parameter in theOne.GetParameters()
join property in properties on (IgnoreCase)parameter.Name equals (IgnoreCase)property.Name
// They definitely match so no comparer is necessary.
// Use either the new value or the current one.
select property.Name == propertyName ? value : property.GetValue(obj);

return (T)theOne.Invoke(parameters.ToArray());




Example



This is how it can be used:



void Main()

var person =
Immutable<Person>
.Builder
.With(x => x.FirstName, "Jane")
.With(x => x.LastName, null)
//.With(x => x.NickName, "JD") // Optional
.Build();

person.With(x => x.LastName, "Doe").Dump();


public class Person

public Person(string firstName, string lastName, string nickName = null)

FirstName = firstName;
LastName = lastName;
NickName = nickName;


// This ctor should confuse the API.
public Person(string other)

public string FirstName get;

public string LastName get;

public string NickName get;

// This property should confuse the API too.
public string FullName => $"LastName, FirstName";




What do you say? Crazy? Insane? I like it? Let's improve it?










share|improve this question











$endgroup$









  • 2




    $begingroup$
    This has a use case for building controllers and what not that have dozens of parameters. Does this also work with optional ctr arguments?
    $endgroup$
    – dfhwze
    9 hours ago






  • 1




    $begingroup$
    @dfhwze it doesn't... but it definitelly could... and should.
    $endgroup$
    – t3chb0t
    9 hours ago










  • $begingroup$
    Ok ... so let's improve it! :p
    $endgroup$
    – dfhwze
    9 hours ago










  • $begingroup$
    @dfhwze done! ;-] at least the main builder can do this now.
    $endgroup$
    – t3chb0t
    9 hours ago







  • 1




    $begingroup$
    I like the With extensions method that helps to create modified copies of mutable types. However I didn't get the use case of the ImmutableBuilder.. Why not just calling the constructor?
    $endgroup$
    – JanDotNet
    6 hours ago













8












8








8


1



$begingroup$


There aren't enough questions about creating immutable objects... so why not try it again with another approach. This time, it's a builder that maps properties to constructor parameters. Properties are selected via the With method that also expects a new value for the parameter. Constructor parameters must match properties so it's primarily for DTOs that follow this pattern. Build tries to find that constructor and creates the object.



// I need this primarily for the left-join of optional parameters.
internal class IgnoreCase : IEquatable<string>

public string Value get; set;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase Value = value ;


public class ImmutableBuilder<T>

private readonly IList<(MemberExpression Selector, object Value)> _selectors = new List<(MemberExpression Selector, object Value)>();

public ImmutableBuilder<T> With<TProperty>(Expression<Func<T, TProperty>> selector, TProperty value)

_selectors.Add(((MemberExpression)selector.Body, value));
return this;


public T Build()

var ctors =
from ctor in typeof(T).GetConstructors()
let parameters = ctor.GetParameters()
// Join parameters and values by parameter order.
// The ctor requires them sorted but they might be initialized in any order.
let requiredParameterValues =
from parameter in parameters.Where(p => !p.IsOptional)
join selector in _selectors on (IgnoreCase)parameter.Name equals (IgnoreCase)selector.Selector.Member.Name
select selector.Value
// Get optional parameters if any.
let optionalParameterValues =
from parameter in parameters.Where(p => p.IsOptional)
join selector in _selectors on (IgnoreCase)parameter.Name equals (IgnoreCase)selector.Selector.Member.Name into s
from selector in s.DefaultIfEmpty()
select selector.Value
// Make sure all required parameters are specified.
where requiredParameterValues.Count() == parameters.Where(p => !p.IsOptional).Count()
select (ctor, requiredParameterValues, optionalParameterValues);

var theOne = ctors.Single();
return (T)theOne.ctor.Invoke(theOne.requiredParameterValues.Concat(theOne.optionalParameterValues).ToArray());



public static class Immutable<T>

public static ImmutableBuilder<T> Builder => new ImmutableBuilder<T>();



In case we already have an immutable type and want to modify it by changing just some values, the ImmutableHelper can be used. It also provides the With method expecting a new value. Then matches it and other properties with the constructor and uses origianl values as defaults and for the specified property the new value.



public static class ImmutableHelper

public static T With<T, TProperty>(this T obj, Expression<Func<T, TProperty>> selector, TProperty value)

var comparer = StringComparer.OrdinalIgnoreCase;

var propertyName = ((MemberExpression)selector.Body).Member.Name;
var properties = typeof(T).GetProperties();

var propertyNames =
properties
.Select(x => x.Name)
// A hash-set is convenient for name matching in the next step.
.ToImmutableHashSet(comparer);

// Find the constructor that matches property names.
var ctors =
from ctor in typeof(T).GetConstructors()
where propertyNames.IsProperSupersetOf(ctor.GetParameters().Select(x => x.Name))
select ctor;

var theOne = ctors.Single(); // There can be only one match.

var parameters =
from parameter in theOne.GetParameters()
join property in properties on (IgnoreCase)parameter.Name equals (IgnoreCase)property.Name
// They definitely match so no comparer is necessary.
// Use either the new value or the current one.
select property.Name == propertyName ? value : property.GetValue(obj);

return (T)theOne.Invoke(parameters.ToArray());




Example



This is how it can be used:



void Main()

var person =
Immutable<Person>
.Builder
.With(x => x.FirstName, "Jane")
.With(x => x.LastName, null)
//.With(x => x.NickName, "JD") // Optional
.Build();

person.With(x => x.LastName, "Doe").Dump();


public class Person

public Person(string firstName, string lastName, string nickName = null)

FirstName = firstName;
LastName = lastName;
NickName = nickName;


// This ctor should confuse the API.
public Person(string other)

public string FirstName get;

public string LastName get;

public string NickName get;

// This property should confuse the API too.
public string FullName => $"LastName, FirstName";




What do you say? Crazy? Insane? I like it? Let's improve it?










share|improve this question











$endgroup$




There aren't enough questions about creating immutable objects... so why not try it again with another approach. This time, it's a builder that maps properties to constructor parameters. Properties are selected via the With method that also expects a new value for the parameter. Constructor parameters must match properties so it's primarily for DTOs that follow this pattern. Build tries to find that constructor and creates the object.



// I need this primarily for the left-join of optional parameters.
internal class IgnoreCase : IEquatable<string>

public string Value get; set;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase Value = value ;


public class ImmutableBuilder<T>

private readonly IList<(MemberExpression Selector, object Value)> _selectors = new List<(MemberExpression Selector, object Value)>();

public ImmutableBuilder<T> With<TProperty>(Expression<Func<T, TProperty>> selector, TProperty value)

_selectors.Add(((MemberExpression)selector.Body, value));
return this;


public T Build()

var ctors =
from ctor in typeof(T).GetConstructors()
let parameters = ctor.GetParameters()
// Join parameters and values by parameter order.
// The ctor requires them sorted but they might be initialized in any order.
let requiredParameterValues =
from parameter in parameters.Where(p => !p.IsOptional)
join selector in _selectors on (IgnoreCase)parameter.Name equals (IgnoreCase)selector.Selector.Member.Name
select selector.Value
// Get optional parameters if any.
let optionalParameterValues =
from parameter in parameters.Where(p => p.IsOptional)
join selector in _selectors on (IgnoreCase)parameter.Name equals (IgnoreCase)selector.Selector.Member.Name into s
from selector in s.DefaultIfEmpty()
select selector.Value
// Make sure all required parameters are specified.
where requiredParameterValues.Count() == parameters.Where(p => !p.IsOptional).Count()
select (ctor, requiredParameterValues, optionalParameterValues);

var theOne = ctors.Single();
return (T)theOne.ctor.Invoke(theOne.requiredParameterValues.Concat(theOne.optionalParameterValues).ToArray());



public static class Immutable<T>

public static ImmutableBuilder<T> Builder => new ImmutableBuilder<T>();



In case we already have an immutable type and want to modify it by changing just some values, the ImmutableHelper can be used. It also provides the With method expecting a new value. Then matches it and other properties with the constructor and uses origianl values as defaults and for the specified property the new value.



public static class ImmutableHelper

public static T With<T, TProperty>(this T obj, Expression<Func<T, TProperty>> selector, TProperty value)

var comparer = StringComparer.OrdinalIgnoreCase;

var propertyName = ((MemberExpression)selector.Body).Member.Name;
var properties = typeof(T).GetProperties();

var propertyNames =
properties
.Select(x => x.Name)
// A hash-set is convenient for name matching in the next step.
.ToImmutableHashSet(comparer);

// Find the constructor that matches property names.
var ctors =
from ctor in typeof(T).GetConstructors()
where propertyNames.IsProperSupersetOf(ctor.GetParameters().Select(x => x.Name))
select ctor;

var theOne = ctors.Single(); // There can be only one match.

var parameters =
from parameter in theOne.GetParameters()
join property in properties on (IgnoreCase)parameter.Name equals (IgnoreCase)property.Name
// They definitely match so no comparer is necessary.
// Use either the new value or the current one.
select property.Name == propertyName ? value : property.GetValue(obj);

return (T)theOne.Invoke(parameters.ToArray());




Example



This is how it can be used:



void Main()

var person =
Immutable<Person>
.Builder
.With(x => x.FirstName, "Jane")
.With(x => x.LastName, null)
//.With(x => x.NickName, "JD") // Optional
.Build();

person.With(x => x.LastName, "Doe").Dump();


public class Person

public Person(string firstName, string lastName, string nickName = null)

FirstName = firstName;
LastName = lastName;
NickName = nickName;


// This ctor should confuse the API.
public Person(string other)

public string FirstName get;

public string LastName get;

public string NickName get;

// This property should confuse the API too.
public string FullName => $"LastName, FirstName";




What do you say? Crazy? Insane? I like it? Let's improve it?







c# generics reflection immutability expression-trees






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 8 hours ago







t3chb0t

















asked 9 hours ago









t3chb0tt3chb0t

37.7k7 gold badges60 silver badges141 bronze badges




37.7k7 gold badges60 silver badges141 bronze badges










  • 2




    $begingroup$
    This has a use case for building controllers and what not that have dozens of parameters. Does this also work with optional ctr arguments?
    $endgroup$
    – dfhwze
    9 hours ago






  • 1




    $begingroup$
    @dfhwze it doesn't... but it definitelly could... and should.
    $endgroup$
    – t3chb0t
    9 hours ago










  • $begingroup$
    Ok ... so let's improve it! :p
    $endgroup$
    – dfhwze
    9 hours ago










  • $begingroup$
    @dfhwze done! ;-] at least the main builder can do this now.
    $endgroup$
    – t3chb0t
    9 hours ago







  • 1




    $begingroup$
    I like the With extensions method that helps to create modified copies of mutable types. However I didn't get the use case of the ImmutableBuilder.. Why not just calling the constructor?
    $endgroup$
    – JanDotNet
    6 hours ago












  • 2




    $begingroup$
    This has a use case for building controllers and what not that have dozens of parameters. Does this also work with optional ctr arguments?
    $endgroup$
    – dfhwze
    9 hours ago






  • 1




    $begingroup$
    @dfhwze it doesn't... but it definitelly could... and should.
    $endgroup$
    – t3chb0t
    9 hours ago










  • $begingroup$
    Ok ... so let's improve it! :p
    $endgroup$
    – dfhwze
    9 hours ago










  • $begingroup$
    @dfhwze done! ;-] at least the main builder can do this now.
    $endgroup$
    – t3chb0t
    9 hours ago







  • 1




    $begingroup$
    I like the With extensions method that helps to create modified copies of mutable types. However I didn't get the use case of the ImmutableBuilder.. Why not just calling the constructor?
    $endgroup$
    – JanDotNet
    6 hours ago







2




2




$begingroup$
This has a use case for building controllers and what not that have dozens of parameters. Does this also work with optional ctr arguments?
$endgroup$
– dfhwze
9 hours ago




$begingroup$
This has a use case for building controllers and what not that have dozens of parameters. Does this also work with optional ctr arguments?
$endgroup$
– dfhwze
9 hours ago




1




1




$begingroup$
@dfhwze it doesn't... but it definitelly could... and should.
$endgroup$
– t3chb0t
9 hours ago




$begingroup$
@dfhwze it doesn't... but it definitelly could... and should.
$endgroup$
– t3chb0t
9 hours ago












$begingroup$
Ok ... so let's improve it! :p
$endgroup$
– dfhwze
9 hours ago




$begingroup$
Ok ... so let's improve it! :p
$endgroup$
– dfhwze
9 hours ago












$begingroup$
@dfhwze done! ;-] at least the main builder can do this now.
$endgroup$
– t3chb0t
9 hours ago





$begingroup$
@dfhwze done! ;-] at least the main builder can do this now.
$endgroup$
– t3chb0t
9 hours ago





1




1




$begingroup$
I like the With extensions method that helps to create modified copies of mutable types. However I didn't get the use case of the ImmutableBuilder.. Why not just calling the constructor?
$endgroup$
– JanDotNet
6 hours ago




$begingroup$
I like the With extensions method that helps to create modified copies of mutable types. However I didn't get the use case of the ImmutableBuilder.. Why not just calling the constructor?
$endgroup$
– JanDotNet
6 hours ago










2 Answers
2






active

oldest

votes


















7













$begingroup$

You use IList<> where you should use ICollection<>. I've rarely encountered a scenario where IList<> actually needs to be used. The ICollection<> interface has most of the list's methods, but without everything related to indexing, which you don't use anyway. It's not that big of a deal, but I think it's good knowledge.




When you search for constructor parameters, I think you should match on parameter types in addition of parameter names. The reason behind this is that this that parameter types with names are guaranteed to be unique, where parameter names could not. For example (it's not a great one, but it's a case that would make your code potentially crash)



class Foobar


public Foobar(string a, int b)



public Foobar(string a, double b)







One problem I see with the Immutable<T> class is that I wouldn't expect a static property to return a new reference every time I call it. I've been trying to find another example in the .NET framework of when this happens, and... I couldn't. I would change it for a method named something like CreateBuilder() or something like that, this way it's clear that we are using a new builder every time we call the method.




I think the Immutable<> type is misleading. When seeing this, I'd expect being able to use it to make some mutable type immutable (however that would be done), but that's not what it does. As a matter of fact, most of your code doesn't rely on the T type to be immutable, which makes me think a tweak or two could make your tool work on mutable types too. In that sense, claiming it's an ImmutableBuilder is kind of wrong, it's a builder that works on immutable types, but on mutable types too.




According to comments, your With method in ImmutableHelper creates a copy of the object with a changed parameter, which is alright considering it doesn't modify the immutable type. What I think could be improved is a similar method with the signature static T With<T, TProperty>(this T obj, IEnmerable<(Expression<Func<T, TProperty>> selector, TProperty value)>), so that if you want to modify more than one field in the object you could do so without having to create a copy of the object every time.






share|improve this answer











$endgroup$














  • $begingroup$
    About the last paragraph... this will go into production (after I made it match parameter types too) because let's say you have an immutable type Uri with such a constructor as scheme, authority, path, query, fragment and you just want to change its scheme from nothing (relative uri) to http and maybe add a fragment. It's mutch easier and reliable to do this with With(x => x.Property, value) and let the framework handle other values than copy all the values yourself... and I once made that mistake of forgetting one of them... I was chasing the bug for 3h :-[
    $endgroup$
    – t3chb0t
    7 hours ago











  • $begingroup$
    @t3chb0t But by doing this you break everything that is expected from an immutable type. If another developer uses the Uri class, he/she will expect it to be immutable. If you happen to use your method somewhere in the code, debugging for this other person will be much more hellish than otherwise. You could use a Copy method then change the necessary fields or something else, maybe.
    $endgroup$
    – IEatBagels
    7 hours ago






  • 1




    $begingroup$
    @t3chb0t Although I understand the bug you've had, it's a tricky bug to find because it's kind of unexpected. I just don't think mutating immutable types is the right solution. Otherwise, maybe your With method could create a new copy of the object
    $endgroup$
    – IEatBagels
    7 hours ago










  • $begingroup$
    Oh, you mean this... yes! It is creating a new copy. The first class is just an initializer and the extension ImmutableHelper.With copies values into a new object. I probably should have put quotes around updater.
    $endgroup$
    – t3chb0t
    7 hours ago











  • $begingroup$
    @t3chb0t oohhh. Let me edit my answer then.
    $endgroup$
    – IEatBagels
    7 hours ago



















0













$begingroup$

(self-answer)




The idea for not-using the constructor is indeed insane but... since it's possible I kept it in the new version too. I changed the name of this tool to DtoUpdater. It now can collect updates for multiple properties that at the end have to be Commited. Parameters are now matched with members not only by name but also by type and it picks the constructor with the most parameters ana matching properties. I created this helper for updating simple DTOs and they usually have only one constructor initializing all properties so I think its current complexity is sufficient for most use-cases.



This version also no longer forces the user to specify all values that a constructor requires. I think that this new functionality now makes this utility in certain situations more useful than using the construtor... if it allows default values of course.



public static class DtoUpdater

public static DtoUpdater<T> For<T>() => new DtoUpdater<T>(default);

public static DtoUpdater<T> Update<T>(this T obj) => new DtoUpdater<T>(obj);


public class DtoUpdater<T>

private readonly T _obj;

private readonly ICollection<(MemberInfo Member, object Value)> _updates = new List<(MemberInfo Member, object Value)>();

public DtoUpdater(T obj) => _obj = obj;

public DtoUpdater<T> With<TProperty>(Expression<Func<T, TProperty>> update, TProperty value)

_updates.Add((((MemberExpression)update.Body).Member, value));
return this;


public T Commit()
BindingFlags.Instance).Where(m => m is PropertyInfo

private object GetMemberValueOrDefault(string memberName)

if (_obj == null) return default;

// There is for sure only one member with that name.
switch (typeof(T).GetMembers(BindingFlags.Public


public static class StringExtensions

public static IEquatable<string> AsIgnoreCase(this string str) => (IgnoreCase)str;

private class IgnoreCase : IEquatable<string>

private IgnoreCase(string value) => Value = value;
private string Value get;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase(value);




I hid the IgnoreCase helper behind a new extension:



public static class StringExtensions

public static IEquatable<string> AsIgnoreCase(this string str) => (IgnoreCase)str;

private class IgnoreCase : IEquatable<string>

private IgnoreCase(string value) => Value = value;
private string Value get;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase(value);




The new API can now be used like this:



public class DtoBuilderTest

[Fact]
public void Can_create_and_update_object()

var person =
DtoUpdater
.For<Person>()
.With(x => x.FirstName, "Jane")
.With(x => x.LastName, null)
//.With(x => x.NickName, "JD") // Optional
.Commit();

Assert.Equal("Jane", person.FirstName);
Assert.Null(person.LastName);
Assert.Null(person.NickName);

person =
person
.Update()
.With(x => x.LastName, "Doe")
.With(x => x.NickName, "JD")
.Commit();

Assert.Equal("Jane", person.FirstName);
Assert.Equal("Doe", person.LastName);
Assert.Equal("JD", person.NickName);


private class Person

public Person(string firstName, string lastName, string nickName = null)

FirstName = firstName;
LastName = lastName;
NickName = nickName;


// This ctor should confuse the API.
public Person(string other)

public string FirstName get;

public string LastName get;

public string NickName get; set;

// This property should confuse the API too.
public string FullName => $"LastName, FirstName";







share|improve this answer









$endgroup$










  • 1




    $begingroup$
    This update/commit pattern makes me think we can tune this up to be used as a batch updater with support for multi-level change tracking/reverting implementing IEditableObject, IChangeTracking and IRevertibleChangeTracking (up-vote pending btw)
    $endgroup$
    – dfhwze
    4 hours ago











  • $begingroup$
    @dfhwze haha don't even think of it. Two more refactoring rounds and it can fly to the moon ;-P
    $endgroup$
    – t3chb0t
    4 hours ago










  • $begingroup$
    I might ask a follow-up question about it in the weekend o_0 But change tracking is not that trivial /o
    $endgroup$
    – dfhwze
    4 hours ago










  • $begingroup$
    @dfhwze I'm not so sure we need all this tracking and undo logic. This demo doesn't show that but usually when you modify an immutable, you pass it so some deeper scope. When it returns, you pick up the previous version for this scope and continue from here. At leat this is how I mostly use immutables. They are convenient to update and use in a new context for a moment. Although it might be useful for debugging.
    $endgroup$
    – t3chb0t
    4 hours ago











  • $begingroup$
    We don't need it for this use case, I want to stea.. 'borrow' your code to make a change tracking API :p Basically, I want your immutable code for my mutable stuff. That's it, I'm no longer making any sense at all ... I'm off to bed, see ya.
    $endgroup$
    – dfhwze
    4 hours ago














Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f226694%2fimmutable-builder-and-updater%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









7













$begingroup$

You use IList<> where you should use ICollection<>. I've rarely encountered a scenario where IList<> actually needs to be used. The ICollection<> interface has most of the list's methods, but without everything related to indexing, which you don't use anyway. It's not that big of a deal, but I think it's good knowledge.




When you search for constructor parameters, I think you should match on parameter types in addition of parameter names. The reason behind this is that this that parameter types with names are guaranteed to be unique, where parameter names could not. For example (it's not a great one, but it's a case that would make your code potentially crash)



class Foobar


public Foobar(string a, int b)



public Foobar(string a, double b)







One problem I see with the Immutable<T> class is that I wouldn't expect a static property to return a new reference every time I call it. I've been trying to find another example in the .NET framework of when this happens, and... I couldn't. I would change it for a method named something like CreateBuilder() or something like that, this way it's clear that we are using a new builder every time we call the method.




I think the Immutable<> type is misleading. When seeing this, I'd expect being able to use it to make some mutable type immutable (however that would be done), but that's not what it does. As a matter of fact, most of your code doesn't rely on the T type to be immutable, which makes me think a tweak or two could make your tool work on mutable types too. In that sense, claiming it's an ImmutableBuilder is kind of wrong, it's a builder that works on immutable types, but on mutable types too.




According to comments, your With method in ImmutableHelper creates a copy of the object with a changed parameter, which is alright considering it doesn't modify the immutable type. What I think could be improved is a similar method with the signature static T With<T, TProperty>(this T obj, IEnmerable<(Expression<Func<T, TProperty>> selector, TProperty value)>), so that if you want to modify more than one field in the object you could do so without having to create a copy of the object every time.






share|improve this answer











$endgroup$














  • $begingroup$
    About the last paragraph... this will go into production (after I made it match parameter types too) because let's say you have an immutable type Uri with such a constructor as scheme, authority, path, query, fragment and you just want to change its scheme from nothing (relative uri) to http and maybe add a fragment. It's mutch easier and reliable to do this with With(x => x.Property, value) and let the framework handle other values than copy all the values yourself... and I once made that mistake of forgetting one of them... I was chasing the bug for 3h :-[
    $endgroup$
    – t3chb0t
    7 hours ago











  • $begingroup$
    @t3chb0t But by doing this you break everything that is expected from an immutable type. If another developer uses the Uri class, he/she will expect it to be immutable. If you happen to use your method somewhere in the code, debugging for this other person will be much more hellish than otherwise. You could use a Copy method then change the necessary fields or something else, maybe.
    $endgroup$
    – IEatBagels
    7 hours ago






  • 1




    $begingroup$
    @t3chb0t Although I understand the bug you've had, it's a tricky bug to find because it's kind of unexpected. I just don't think mutating immutable types is the right solution. Otherwise, maybe your With method could create a new copy of the object
    $endgroup$
    – IEatBagels
    7 hours ago










  • $begingroup$
    Oh, you mean this... yes! It is creating a new copy. The first class is just an initializer and the extension ImmutableHelper.With copies values into a new object. I probably should have put quotes around updater.
    $endgroup$
    – t3chb0t
    7 hours ago











  • $begingroup$
    @t3chb0t oohhh. Let me edit my answer then.
    $endgroup$
    – IEatBagels
    7 hours ago
















7













$begingroup$

You use IList<> where you should use ICollection<>. I've rarely encountered a scenario where IList<> actually needs to be used. The ICollection<> interface has most of the list's methods, but without everything related to indexing, which you don't use anyway. It's not that big of a deal, but I think it's good knowledge.




When you search for constructor parameters, I think you should match on parameter types in addition of parameter names. The reason behind this is that this that parameter types with names are guaranteed to be unique, where parameter names could not. For example (it's not a great one, but it's a case that would make your code potentially crash)



class Foobar


public Foobar(string a, int b)



public Foobar(string a, double b)







One problem I see with the Immutable<T> class is that I wouldn't expect a static property to return a new reference every time I call it. I've been trying to find another example in the .NET framework of when this happens, and... I couldn't. I would change it for a method named something like CreateBuilder() or something like that, this way it's clear that we are using a new builder every time we call the method.




I think the Immutable<> type is misleading. When seeing this, I'd expect being able to use it to make some mutable type immutable (however that would be done), but that's not what it does. As a matter of fact, most of your code doesn't rely on the T type to be immutable, which makes me think a tweak or two could make your tool work on mutable types too. In that sense, claiming it's an ImmutableBuilder is kind of wrong, it's a builder that works on immutable types, but on mutable types too.




According to comments, your With method in ImmutableHelper creates a copy of the object with a changed parameter, which is alright considering it doesn't modify the immutable type. What I think could be improved is a similar method with the signature static T With<T, TProperty>(this T obj, IEnmerable<(Expression<Func<T, TProperty>> selector, TProperty value)>), so that if you want to modify more than one field in the object you could do so without having to create a copy of the object every time.






share|improve this answer











$endgroup$














  • $begingroup$
    About the last paragraph... this will go into production (after I made it match parameter types too) because let's say you have an immutable type Uri with such a constructor as scheme, authority, path, query, fragment and you just want to change its scheme from nothing (relative uri) to http and maybe add a fragment. It's mutch easier and reliable to do this with With(x => x.Property, value) and let the framework handle other values than copy all the values yourself... and I once made that mistake of forgetting one of them... I was chasing the bug for 3h :-[
    $endgroup$
    – t3chb0t
    7 hours ago











  • $begingroup$
    @t3chb0t But by doing this you break everything that is expected from an immutable type. If another developer uses the Uri class, he/she will expect it to be immutable. If you happen to use your method somewhere in the code, debugging for this other person will be much more hellish than otherwise. You could use a Copy method then change the necessary fields or something else, maybe.
    $endgroup$
    – IEatBagels
    7 hours ago






  • 1




    $begingroup$
    @t3chb0t Although I understand the bug you've had, it's a tricky bug to find because it's kind of unexpected. I just don't think mutating immutable types is the right solution. Otherwise, maybe your With method could create a new copy of the object
    $endgroup$
    – IEatBagels
    7 hours ago










  • $begingroup$
    Oh, you mean this... yes! It is creating a new copy. The first class is just an initializer and the extension ImmutableHelper.With copies values into a new object. I probably should have put quotes around updater.
    $endgroup$
    – t3chb0t
    7 hours ago











  • $begingroup$
    @t3chb0t oohhh. Let me edit my answer then.
    $endgroup$
    – IEatBagels
    7 hours ago














7














7










7







$begingroup$

You use IList<> where you should use ICollection<>. I've rarely encountered a scenario where IList<> actually needs to be used. The ICollection<> interface has most of the list's methods, but without everything related to indexing, which you don't use anyway. It's not that big of a deal, but I think it's good knowledge.




When you search for constructor parameters, I think you should match on parameter types in addition of parameter names. The reason behind this is that this that parameter types with names are guaranteed to be unique, where parameter names could not. For example (it's not a great one, but it's a case that would make your code potentially crash)



class Foobar


public Foobar(string a, int b)



public Foobar(string a, double b)







One problem I see with the Immutable<T> class is that I wouldn't expect a static property to return a new reference every time I call it. I've been trying to find another example in the .NET framework of when this happens, and... I couldn't. I would change it for a method named something like CreateBuilder() or something like that, this way it's clear that we are using a new builder every time we call the method.




I think the Immutable<> type is misleading. When seeing this, I'd expect being able to use it to make some mutable type immutable (however that would be done), but that's not what it does. As a matter of fact, most of your code doesn't rely on the T type to be immutable, which makes me think a tweak or two could make your tool work on mutable types too. In that sense, claiming it's an ImmutableBuilder is kind of wrong, it's a builder that works on immutable types, but on mutable types too.




According to comments, your With method in ImmutableHelper creates a copy of the object with a changed parameter, which is alright considering it doesn't modify the immutable type. What I think could be improved is a similar method with the signature static T With<T, TProperty>(this T obj, IEnmerable<(Expression<Func<T, TProperty>> selector, TProperty value)>), so that if you want to modify more than one field in the object you could do so without having to create a copy of the object every time.






share|improve this answer











$endgroup$



You use IList<> where you should use ICollection<>. I've rarely encountered a scenario where IList<> actually needs to be used. The ICollection<> interface has most of the list's methods, but without everything related to indexing, which you don't use anyway. It's not that big of a deal, but I think it's good knowledge.




When you search for constructor parameters, I think you should match on parameter types in addition of parameter names. The reason behind this is that this that parameter types with names are guaranteed to be unique, where parameter names could not. For example (it's not a great one, but it's a case that would make your code potentially crash)



class Foobar


public Foobar(string a, int b)



public Foobar(string a, double b)







One problem I see with the Immutable<T> class is that I wouldn't expect a static property to return a new reference every time I call it. I've been trying to find another example in the .NET framework of when this happens, and... I couldn't. I would change it for a method named something like CreateBuilder() or something like that, this way it's clear that we are using a new builder every time we call the method.




I think the Immutable<> type is misleading. When seeing this, I'd expect being able to use it to make some mutable type immutable (however that would be done), but that's not what it does. As a matter of fact, most of your code doesn't rely on the T type to be immutable, which makes me think a tweak or two could make your tool work on mutable types too. In that sense, claiming it's an ImmutableBuilder is kind of wrong, it's a builder that works on immutable types, but on mutable types too.




According to comments, your With method in ImmutableHelper creates a copy of the object with a changed parameter, which is alright considering it doesn't modify the immutable type. What I think could be improved is a similar method with the signature static T With<T, TProperty>(this T obj, IEnmerable<(Expression<Func<T, TProperty>> selector, TProperty value)>), so that if you want to modify more than one field in the object you could do so without having to create a copy of the object every time.







share|improve this answer














share|improve this answer



share|improve this answer








edited 7 hours ago

























answered 7 hours ago









IEatBagelsIEatBagels

9,9502 gold badges35 silver badges86 bronze badges




9,9502 gold badges35 silver badges86 bronze badges














  • $begingroup$
    About the last paragraph... this will go into production (after I made it match parameter types too) because let's say you have an immutable type Uri with such a constructor as scheme, authority, path, query, fragment and you just want to change its scheme from nothing (relative uri) to http and maybe add a fragment. It's mutch easier and reliable to do this with With(x => x.Property, value) and let the framework handle other values than copy all the values yourself... and I once made that mistake of forgetting one of them... I was chasing the bug for 3h :-[
    $endgroup$
    – t3chb0t
    7 hours ago











  • $begingroup$
    @t3chb0t But by doing this you break everything that is expected from an immutable type. If another developer uses the Uri class, he/she will expect it to be immutable. If you happen to use your method somewhere in the code, debugging for this other person will be much more hellish than otherwise. You could use a Copy method then change the necessary fields or something else, maybe.
    $endgroup$
    – IEatBagels
    7 hours ago






  • 1




    $begingroup$
    @t3chb0t Although I understand the bug you've had, it's a tricky bug to find because it's kind of unexpected. I just don't think mutating immutable types is the right solution. Otherwise, maybe your With method could create a new copy of the object
    $endgroup$
    – IEatBagels
    7 hours ago










  • $begingroup$
    Oh, you mean this... yes! It is creating a new copy. The first class is just an initializer and the extension ImmutableHelper.With copies values into a new object. I probably should have put quotes around updater.
    $endgroup$
    – t3chb0t
    7 hours ago











  • $begingroup$
    @t3chb0t oohhh. Let me edit my answer then.
    $endgroup$
    – IEatBagels
    7 hours ago

















  • $begingroup$
    About the last paragraph... this will go into production (after I made it match parameter types too) because let's say you have an immutable type Uri with such a constructor as scheme, authority, path, query, fragment and you just want to change its scheme from nothing (relative uri) to http and maybe add a fragment. It's mutch easier and reliable to do this with With(x => x.Property, value) and let the framework handle other values than copy all the values yourself... and I once made that mistake of forgetting one of them... I was chasing the bug for 3h :-[
    $endgroup$
    – t3chb0t
    7 hours ago











  • $begingroup$
    @t3chb0t But by doing this you break everything that is expected from an immutable type. If another developer uses the Uri class, he/she will expect it to be immutable. If you happen to use your method somewhere in the code, debugging for this other person will be much more hellish than otherwise. You could use a Copy method then change the necessary fields or something else, maybe.
    $endgroup$
    – IEatBagels
    7 hours ago






  • 1




    $begingroup$
    @t3chb0t Although I understand the bug you've had, it's a tricky bug to find because it's kind of unexpected. I just don't think mutating immutable types is the right solution. Otherwise, maybe your With method could create a new copy of the object
    $endgroup$
    – IEatBagels
    7 hours ago










  • $begingroup$
    Oh, you mean this... yes! It is creating a new copy. The first class is just an initializer and the extension ImmutableHelper.With copies values into a new object. I probably should have put quotes around updater.
    $endgroup$
    – t3chb0t
    7 hours ago











  • $begingroup$
    @t3chb0t oohhh. Let me edit my answer then.
    $endgroup$
    – IEatBagels
    7 hours ago
















$begingroup$
About the last paragraph... this will go into production (after I made it match parameter types too) because let's say you have an immutable type Uri with such a constructor as scheme, authority, path, query, fragment and you just want to change its scheme from nothing (relative uri) to http and maybe add a fragment. It's mutch easier and reliable to do this with With(x => x.Property, value) and let the framework handle other values than copy all the values yourself... and I once made that mistake of forgetting one of them... I was chasing the bug for 3h :-[
$endgroup$
– t3chb0t
7 hours ago





$begingroup$
About the last paragraph... this will go into production (after I made it match parameter types too) because let's say you have an immutable type Uri with such a constructor as scheme, authority, path, query, fragment and you just want to change its scheme from nothing (relative uri) to http and maybe add a fragment. It's mutch easier and reliable to do this with With(x => x.Property, value) and let the framework handle other values than copy all the values yourself... and I once made that mistake of forgetting one of them... I was chasing the bug for 3h :-[
$endgroup$
– t3chb0t
7 hours ago













$begingroup$
@t3chb0t But by doing this you break everything that is expected from an immutable type. If another developer uses the Uri class, he/she will expect it to be immutable. If you happen to use your method somewhere in the code, debugging for this other person will be much more hellish than otherwise. You could use a Copy method then change the necessary fields or something else, maybe.
$endgroup$
– IEatBagels
7 hours ago




$begingroup$
@t3chb0t But by doing this you break everything that is expected from an immutable type. If another developer uses the Uri class, he/she will expect it to be immutable. If you happen to use your method somewhere in the code, debugging for this other person will be much more hellish than otherwise. You could use a Copy method then change the necessary fields or something else, maybe.
$endgroup$
– IEatBagels
7 hours ago




1




1




$begingroup$
@t3chb0t Although I understand the bug you've had, it's a tricky bug to find because it's kind of unexpected. I just don't think mutating immutable types is the right solution. Otherwise, maybe your With method could create a new copy of the object
$endgroup$
– IEatBagels
7 hours ago




$begingroup$
@t3chb0t Although I understand the bug you've had, it's a tricky bug to find because it's kind of unexpected. I just don't think mutating immutable types is the right solution. Otherwise, maybe your With method could create a new copy of the object
$endgroup$
– IEatBagels
7 hours ago












$begingroup$
Oh, you mean this... yes! It is creating a new copy. The first class is just an initializer and the extension ImmutableHelper.With copies values into a new object. I probably should have put quotes around updater.
$endgroup$
– t3chb0t
7 hours ago





$begingroup$
Oh, you mean this... yes! It is creating a new copy. The first class is just an initializer and the extension ImmutableHelper.With copies values into a new object. I probably should have put quotes around updater.
$endgroup$
– t3chb0t
7 hours ago













$begingroup$
@t3chb0t oohhh. Let me edit my answer then.
$endgroup$
– IEatBagels
7 hours ago





$begingroup$
@t3chb0t oohhh. Let me edit my answer then.
$endgroup$
– IEatBagels
7 hours ago














0













$begingroup$

(self-answer)




The idea for not-using the constructor is indeed insane but... since it's possible I kept it in the new version too. I changed the name of this tool to DtoUpdater. It now can collect updates for multiple properties that at the end have to be Commited. Parameters are now matched with members not only by name but also by type and it picks the constructor with the most parameters ana matching properties. I created this helper for updating simple DTOs and they usually have only one constructor initializing all properties so I think its current complexity is sufficient for most use-cases.



This version also no longer forces the user to specify all values that a constructor requires. I think that this new functionality now makes this utility in certain situations more useful than using the construtor... if it allows default values of course.



public static class DtoUpdater

public static DtoUpdater<T> For<T>() => new DtoUpdater<T>(default);

public static DtoUpdater<T> Update<T>(this T obj) => new DtoUpdater<T>(obj);


public class DtoUpdater<T>

private readonly T _obj;

private readonly ICollection<(MemberInfo Member, object Value)> _updates = new List<(MemberInfo Member, object Value)>();

public DtoUpdater(T obj) => _obj = obj;

public DtoUpdater<T> With<TProperty>(Expression<Func<T, TProperty>> update, TProperty value)

_updates.Add((((MemberExpression)update.Body).Member, value));
return this;


public T Commit()
BindingFlags.Instance).Where(m => m is PropertyInfo

private object GetMemberValueOrDefault(string memberName)

if (_obj == null) return default;

// There is for sure only one member with that name.
switch (typeof(T).GetMembers(BindingFlags.Public


public static class StringExtensions

public static IEquatable<string> AsIgnoreCase(this string str) => (IgnoreCase)str;

private class IgnoreCase : IEquatable<string>

private IgnoreCase(string value) => Value = value;
private string Value get;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase(value);




I hid the IgnoreCase helper behind a new extension:



public static class StringExtensions

public static IEquatable<string> AsIgnoreCase(this string str) => (IgnoreCase)str;

private class IgnoreCase : IEquatable<string>

private IgnoreCase(string value) => Value = value;
private string Value get;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase(value);




The new API can now be used like this:



public class DtoBuilderTest

[Fact]
public void Can_create_and_update_object()

var person =
DtoUpdater
.For<Person>()
.With(x => x.FirstName, "Jane")
.With(x => x.LastName, null)
//.With(x => x.NickName, "JD") // Optional
.Commit();

Assert.Equal("Jane", person.FirstName);
Assert.Null(person.LastName);
Assert.Null(person.NickName);

person =
person
.Update()
.With(x => x.LastName, "Doe")
.With(x => x.NickName, "JD")
.Commit();

Assert.Equal("Jane", person.FirstName);
Assert.Equal("Doe", person.LastName);
Assert.Equal("JD", person.NickName);


private class Person

public Person(string firstName, string lastName, string nickName = null)

FirstName = firstName;
LastName = lastName;
NickName = nickName;


// This ctor should confuse the API.
public Person(string other)

public string FirstName get;

public string LastName get;

public string NickName get; set;

// This property should confuse the API too.
public string FullName => $"LastName, FirstName";







share|improve this answer









$endgroup$










  • 1




    $begingroup$
    This update/commit pattern makes me think we can tune this up to be used as a batch updater with support for multi-level change tracking/reverting implementing IEditableObject, IChangeTracking and IRevertibleChangeTracking (up-vote pending btw)
    $endgroup$
    – dfhwze
    4 hours ago











  • $begingroup$
    @dfhwze haha don't even think of it. Two more refactoring rounds and it can fly to the moon ;-P
    $endgroup$
    – t3chb0t
    4 hours ago










  • $begingroup$
    I might ask a follow-up question about it in the weekend o_0 But change tracking is not that trivial /o
    $endgroup$
    – dfhwze
    4 hours ago










  • $begingroup$
    @dfhwze I'm not so sure we need all this tracking and undo logic. This demo doesn't show that but usually when you modify an immutable, you pass it so some deeper scope. When it returns, you pick up the previous version for this scope and continue from here. At leat this is how I mostly use immutables. They are convenient to update and use in a new context for a moment. Although it might be useful for debugging.
    $endgroup$
    – t3chb0t
    4 hours ago











  • $begingroup$
    We don't need it for this use case, I want to stea.. 'borrow' your code to make a change tracking API :p Basically, I want your immutable code for my mutable stuff. That's it, I'm no longer making any sense at all ... I'm off to bed, see ya.
    $endgroup$
    – dfhwze
    4 hours ago
















0













$begingroup$

(self-answer)




The idea for not-using the constructor is indeed insane but... since it's possible I kept it in the new version too. I changed the name of this tool to DtoUpdater. It now can collect updates for multiple properties that at the end have to be Commited. Parameters are now matched with members not only by name but also by type and it picks the constructor with the most parameters ana matching properties. I created this helper for updating simple DTOs and they usually have only one constructor initializing all properties so I think its current complexity is sufficient for most use-cases.



This version also no longer forces the user to specify all values that a constructor requires. I think that this new functionality now makes this utility in certain situations more useful than using the construtor... if it allows default values of course.



public static class DtoUpdater

public static DtoUpdater<T> For<T>() => new DtoUpdater<T>(default);

public static DtoUpdater<T> Update<T>(this T obj) => new DtoUpdater<T>(obj);


public class DtoUpdater<T>

private readonly T _obj;

private readonly ICollection<(MemberInfo Member, object Value)> _updates = new List<(MemberInfo Member, object Value)>();

public DtoUpdater(T obj) => _obj = obj;

public DtoUpdater<T> With<TProperty>(Expression<Func<T, TProperty>> update, TProperty value)

_updates.Add((((MemberExpression)update.Body).Member, value));
return this;


public T Commit()
BindingFlags.Instance).Where(m => m is PropertyInfo

private object GetMemberValueOrDefault(string memberName)

if (_obj == null) return default;

// There is for sure only one member with that name.
switch (typeof(T).GetMembers(BindingFlags.Public


public static class StringExtensions

public static IEquatable<string> AsIgnoreCase(this string str) => (IgnoreCase)str;

private class IgnoreCase : IEquatable<string>

private IgnoreCase(string value) => Value = value;
private string Value get;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase(value);




I hid the IgnoreCase helper behind a new extension:



public static class StringExtensions

public static IEquatable<string> AsIgnoreCase(this string str) => (IgnoreCase)str;

private class IgnoreCase : IEquatable<string>

private IgnoreCase(string value) => Value = value;
private string Value get;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase(value);




The new API can now be used like this:



public class DtoBuilderTest

[Fact]
public void Can_create_and_update_object()

var person =
DtoUpdater
.For<Person>()
.With(x => x.FirstName, "Jane")
.With(x => x.LastName, null)
//.With(x => x.NickName, "JD") // Optional
.Commit();

Assert.Equal("Jane", person.FirstName);
Assert.Null(person.LastName);
Assert.Null(person.NickName);

person =
person
.Update()
.With(x => x.LastName, "Doe")
.With(x => x.NickName, "JD")
.Commit();

Assert.Equal("Jane", person.FirstName);
Assert.Equal("Doe", person.LastName);
Assert.Equal("JD", person.NickName);


private class Person

public Person(string firstName, string lastName, string nickName = null)

FirstName = firstName;
LastName = lastName;
NickName = nickName;


// This ctor should confuse the API.
public Person(string other)

public string FirstName get;

public string LastName get;

public string NickName get; set;

// This property should confuse the API too.
public string FullName => $"LastName, FirstName";







share|improve this answer









$endgroup$










  • 1




    $begingroup$
    This update/commit pattern makes me think we can tune this up to be used as a batch updater with support for multi-level change tracking/reverting implementing IEditableObject, IChangeTracking and IRevertibleChangeTracking (up-vote pending btw)
    $endgroup$
    – dfhwze
    4 hours ago











  • $begingroup$
    @dfhwze haha don't even think of it. Two more refactoring rounds and it can fly to the moon ;-P
    $endgroup$
    – t3chb0t
    4 hours ago










  • $begingroup$
    I might ask a follow-up question about it in the weekend o_0 But change tracking is not that trivial /o
    $endgroup$
    – dfhwze
    4 hours ago










  • $begingroup$
    @dfhwze I'm not so sure we need all this tracking and undo logic. This demo doesn't show that but usually when you modify an immutable, you pass it so some deeper scope. When it returns, you pick up the previous version for this scope and continue from here. At leat this is how I mostly use immutables. They are convenient to update and use in a new context for a moment. Although it might be useful for debugging.
    $endgroup$
    – t3chb0t
    4 hours ago











  • $begingroup$
    We don't need it for this use case, I want to stea.. 'borrow' your code to make a change tracking API :p Basically, I want your immutable code for my mutable stuff. That's it, I'm no longer making any sense at all ... I'm off to bed, see ya.
    $endgroup$
    – dfhwze
    4 hours ago














0














0










0







$begingroup$

(self-answer)




The idea for not-using the constructor is indeed insane but... since it's possible I kept it in the new version too. I changed the name of this tool to DtoUpdater. It now can collect updates for multiple properties that at the end have to be Commited. Parameters are now matched with members not only by name but also by type and it picks the constructor with the most parameters ana matching properties. I created this helper for updating simple DTOs and they usually have only one constructor initializing all properties so I think its current complexity is sufficient for most use-cases.



This version also no longer forces the user to specify all values that a constructor requires. I think that this new functionality now makes this utility in certain situations more useful than using the construtor... if it allows default values of course.



public static class DtoUpdater

public static DtoUpdater<T> For<T>() => new DtoUpdater<T>(default);

public static DtoUpdater<T> Update<T>(this T obj) => new DtoUpdater<T>(obj);


public class DtoUpdater<T>

private readonly T _obj;

private readonly ICollection<(MemberInfo Member, object Value)> _updates = new List<(MemberInfo Member, object Value)>();

public DtoUpdater(T obj) => _obj = obj;

public DtoUpdater<T> With<TProperty>(Expression<Func<T, TProperty>> update, TProperty value)

_updates.Add((((MemberExpression)update.Body).Member, value));
return this;


public T Commit()
BindingFlags.Instance).Where(m => m is PropertyInfo

private object GetMemberValueOrDefault(string memberName)

if (_obj == null) return default;

// There is for sure only one member with that name.
switch (typeof(T).GetMembers(BindingFlags.Public


public static class StringExtensions

public static IEquatable<string> AsIgnoreCase(this string str) => (IgnoreCase)str;

private class IgnoreCase : IEquatable<string>

private IgnoreCase(string value) => Value = value;
private string Value get;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase(value);




I hid the IgnoreCase helper behind a new extension:



public static class StringExtensions

public static IEquatable<string> AsIgnoreCase(this string str) => (IgnoreCase)str;

private class IgnoreCase : IEquatable<string>

private IgnoreCase(string value) => Value = value;
private string Value get;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase(value);




The new API can now be used like this:



public class DtoBuilderTest

[Fact]
public void Can_create_and_update_object()

var person =
DtoUpdater
.For<Person>()
.With(x => x.FirstName, "Jane")
.With(x => x.LastName, null)
//.With(x => x.NickName, "JD") // Optional
.Commit();

Assert.Equal("Jane", person.FirstName);
Assert.Null(person.LastName);
Assert.Null(person.NickName);

person =
person
.Update()
.With(x => x.LastName, "Doe")
.With(x => x.NickName, "JD")
.Commit();

Assert.Equal("Jane", person.FirstName);
Assert.Equal("Doe", person.LastName);
Assert.Equal("JD", person.NickName);


private class Person

public Person(string firstName, string lastName, string nickName = null)

FirstName = firstName;
LastName = lastName;
NickName = nickName;


// This ctor should confuse the API.
public Person(string other)

public string FirstName get;

public string LastName get;

public string NickName get; set;

// This property should confuse the API too.
public string FullName => $"LastName, FirstName";







share|improve this answer









$endgroup$



(self-answer)




The idea for not-using the constructor is indeed insane but... since it's possible I kept it in the new version too. I changed the name of this tool to DtoUpdater. It now can collect updates for multiple properties that at the end have to be Commited. Parameters are now matched with members not only by name but also by type and it picks the constructor with the most parameters ana matching properties. I created this helper for updating simple DTOs and they usually have only one constructor initializing all properties so I think its current complexity is sufficient for most use-cases.



This version also no longer forces the user to specify all values that a constructor requires. I think that this new functionality now makes this utility in certain situations more useful than using the construtor... if it allows default values of course.



public static class DtoUpdater

public static DtoUpdater<T> For<T>() => new DtoUpdater<T>(default);

public static DtoUpdater<T> Update<T>(this T obj) => new DtoUpdater<T>(obj);


public class DtoUpdater<T>

private readonly T _obj;

private readonly ICollection<(MemberInfo Member, object Value)> _updates = new List<(MemberInfo Member, object Value)>();

public DtoUpdater(T obj) => _obj = obj;

public DtoUpdater<T> With<TProperty>(Expression<Func<T, TProperty>> update, TProperty value)

_updates.Add((((MemberExpression)update.Body).Member, value));
return this;


public T Commit()
BindingFlags.Instance).Where(m => m is PropertyInfo

private object GetMemberValueOrDefault(string memberName)

if (_obj == null) return default;

// There is for sure only one member with that name.
switch (typeof(T).GetMembers(BindingFlags.Public


public static class StringExtensions

public static IEquatable<string> AsIgnoreCase(this string str) => (IgnoreCase)str;

private class IgnoreCase : IEquatable<string>

private IgnoreCase(string value) => Value = value;
private string Value get;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase(value);




I hid the IgnoreCase helper behind a new extension:



public static class StringExtensions

public static IEquatable<string> AsIgnoreCase(this string str) => (IgnoreCase)str;

private class IgnoreCase : IEquatable<string>

private IgnoreCase(string value) => Value = value;
private string Value get;
public bool Equals(string other) => StringComparer.OrdinalIgnoreCase.Equals(Value, other);
public override bool Equals(object obj) => obj is IgnoreCase ic && Equals(ic.Value);
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Value);
public static explicit operator IgnoreCase(string value) => new IgnoreCase(value);




The new API can now be used like this:



public class DtoBuilderTest

[Fact]
public void Can_create_and_update_object()

var person =
DtoUpdater
.For<Person>()
.With(x => x.FirstName, "Jane")
.With(x => x.LastName, null)
//.With(x => x.NickName, "JD") // Optional
.Commit();

Assert.Equal("Jane", person.FirstName);
Assert.Null(person.LastName);
Assert.Null(person.NickName);

person =
person
.Update()
.With(x => x.LastName, "Doe")
.With(x => x.NickName, "JD")
.Commit();

Assert.Equal("Jane", person.FirstName);
Assert.Equal("Doe", person.LastName);
Assert.Equal("JD", person.NickName);


private class Person

public Person(string firstName, string lastName, string nickName = null)

FirstName = firstName;
LastName = lastName;
NickName = nickName;


// This ctor should confuse the API.
public Person(string other)

public string FirstName get;

public string LastName get;

public string NickName get; set;

// This property should confuse the API too.
public string FullName => $"LastName, FirstName";








share|improve this answer












share|improve this answer



share|improve this answer










answered 4 hours ago









t3chb0tt3chb0t

37.7k7 gold badges60 silver badges141 bronze badges




37.7k7 gold badges60 silver badges141 bronze badges










  • 1




    $begingroup$
    This update/commit pattern makes me think we can tune this up to be used as a batch updater with support for multi-level change tracking/reverting implementing IEditableObject, IChangeTracking and IRevertibleChangeTracking (up-vote pending btw)
    $endgroup$
    – dfhwze
    4 hours ago











  • $begingroup$
    @dfhwze haha don't even think of it. Two more refactoring rounds and it can fly to the moon ;-P
    $endgroup$
    – t3chb0t
    4 hours ago










  • $begingroup$
    I might ask a follow-up question about it in the weekend o_0 But change tracking is not that trivial /o
    $endgroup$
    – dfhwze
    4 hours ago










  • $begingroup$
    @dfhwze I'm not so sure we need all this tracking and undo logic. This demo doesn't show that but usually when you modify an immutable, you pass it so some deeper scope. When it returns, you pick up the previous version for this scope and continue from here. At leat this is how I mostly use immutables. They are convenient to update and use in a new context for a moment. Although it might be useful for debugging.
    $endgroup$
    – t3chb0t
    4 hours ago











  • $begingroup$
    We don't need it for this use case, I want to stea.. 'borrow' your code to make a change tracking API :p Basically, I want your immutable code for my mutable stuff. That's it, I'm no longer making any sense at all ... I'm off to bed, see ya.
    $endgroup$
    – dfhwze
    4 hours ago













  • 1




    $begingroup$
    This update/commit pattern makes me think we can tune this up to be used as a batch updater with support for multi-level change tracking/reverting implementing IEditableObject, IChangeTracking and IRevertibleChangeTracking (up-vote pending btw)
    $endgroup$
    – dfhwze
    4 hours ago











  • $begingroup$
    @dfhwze haha don't even think of it. Two more refactoring rounds and it can fly to the moon ;-P
    $endgroup$
    – t3chb0t
    4 hours ago










  • $begingroup$
    I might ask a follow-up question about it in the weekend o_0 But change tracking is not that trivial /o
    $endgroup$
    – dfhwze
    4 hours ago










  • $begingroup$
    @dfhwze I'm not so sure we need all this tracking and undo logic. This demo doesn't show that but usually when you modify an immutable, you pass it so some deeper scope. When it returns, you pick up the previous version for this scope and continue from here. At leat this is how I mostly use immutables. They are convenient to update and use in a new context for a moment. Although it might be useful for debugging.
    $endgroup$
    – t3chb0t
    4 hours ago











  • $begingroup$
    We don't need it for this use case, I want to stea.. 'borrow' your code to make a change tracking API :p Basically, I want your immutable code for my mutable stuff. That's it, I'm no longer making any sense at all ... I'm off to bed, see ya.
    $endgroup$
    – dfhwze
    4 hours ago








1




1




$begingroup$
This update/commit pattern makes me think we can tune this up to be used as a batch updater with support for multi-level change tracking/reverting implementing IEditableObject, IChangeTracking and IRevertibleChangeTracking (up-vote pending btw)
$endgroup$
– dfhwze
4 hours ago





$begingroup$
This update/commit pattern makes me think we can tune this up to be used as a batch updater with support for multi-level change tracking/reverting implementing IEditableObject, IChangeTracking and IRevertibleChangeTracking (up-vote pending btw)
$endgroup$
– dfhwze
4 hours ago













$begingroup$
@dfhwze haha don't even think of it. Two more refactoring rounds and it can fly to the moon ;-P
$endgroup$
– t3chb0t
4 hours ago




$begingroup$
@dfhwze haha don't even think of it. Two more refactoring rounds and it can fly to the moon ;-P
$endgroup$
– t3chb0t
4 hours ago












$begingroup$
I might ask a follow-up question about it in the weekend o_0 But change tracking is not that trivial /o
$endgroup$
– dfhwze
4 hours ago




$begingroup$
I might ask a follow-up question about it in the weekend o_0 But change tracking is not that trivial /o
$endgroup$
– dfhwze
4 hours ago












$begingroup$
@dfhwze I'm not so sure we need all this tracking and undo logic. This demo doesn't show that but usually when you modify an immutable, you pass it so some deeper scope. When it returns, you pick up the previous version for this scope and continue from here. At leat this is how I mostly use immutables. They are convenient to update and use in a new context for a moment. Although it might be useful for debugging.
$endgroup$
– t3chb0t
4 hours ago





$begingroup$
@dfhwze I'm not so sure we need all this tracking and undo logic. This demo doesn't show that but usually when you modify an immutable, you pass it so some deeper scope. When it returns, you pick up the previous version for this scope and continue from here. At leat this is how I mostly use immutables. They are convenient to update and use in a new context for a moment. Although it might be useful for debugging.
$endgroup$
– t3chb0t
4 hours ago













$begingroup$
We don't need it for this use case, I want to stea.. 'borrow' your code to make a change tracking API :p Basically, I want your immutable code for my mutable stuff. That's it, I'm no longer making any sense at all ... I'm off to bed, see ya.
$endgroup$
– dfhwze
4 hours ago





$begingroup$
We don't need it for this use case, I want to stea.. 'borrow' your code to make a change tracking API :p Basically, I want your immutable code for my mutable stuff. That's it, I'm no longer making any sense at all ... I'm off to bed, see ya.
$endgroup$
– dfhwze
4 hours ago


















draft saved

draft discarded
















































Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f226694%2fimmutable-builder-and-updater%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

19. јануар Садржај Догађаји Рођења Смрти Празници и дани сећања Види још Референце Мени за навигацијуу

Israel Cuprins Etimologie | Istorie | Geografie | Politică | Demografie | Educație | Economie | Cultură | Note explicative | Note bibliografice | Bibliografie | Legături externe | Meniu de navigaresite web oficialfacebooktweeterGoogle+Instagramcanal YouTubeInstagramtextmodificaremodificarewww.technion.ac.ilnew.huji.ac.ilwww.weizmann.ac.ilwww1.biu.ac.ilenglish.tau.ac.ilwww.haifa.ac.ilin.bgu.ac.ilwww.openu.ac.ilwww.ariel.ac.ilCIA FactbookHarta Israelului"Negotiating Jerusalem," Palestine–Israel JournalThe Schizoid Nature of Modern Hebrew: A Slavic Language in Search of a Semitic Past„Arabic in Israel: an official language and a cultural bridge”„Latest Population Statistics for Israel”„Israel Population”„Tables”„Report for Selected Countries and Subjects”Human Development Report 2016: Human Development for Everyone„Distribution of family income - Gini index”The World FactbookJerusalem Law„Israel”„Israel”„Zionist Leaders: David Ben-Gurion 1886–1973”„The status of Jerusalem”„Analysis: Kadima's big plans”„Israel's Hard-Learned Lessons”„The Legacy of Undefined Borders, Tel Aviv Notes No. 40, 5 iunie 2002”„Israel Journal: A Land Without Borders”„Population”„Israel closes decade with population of 7.5 million”Time Series-DataBank„Selected Statistics on Jerusalem Day 2007 (Hebrew)”Golan belongs to Syria, Druze protestGlobal Survey 2006: Middle East Progress Amid Global Gains in FreedomWHO: Life expectancy in Israel among highest in the worldInternational Monetary Fund, World Economic Outlook Database, April 2011: Nominal GDP list of countries. Data for the year 2010.„Israel's accession to the OECD”Popular Opinion„On the Move”Hosea 12:5„Walking the Bible Timeline”„Palestine: History”„Return to Zion”An invention called 'the Jewish people' – Haaretz – Israel NewsoriginalJewish and Non-Jewish Population of Palestine-Israel (1517–2004)ImmigrationJewishvirtuallibrary.orgChapter One: The Heralders of Zionism„The birth of modern Israel: A scrap of paper that changed history”„League of Nations: The Mandate for Palestine, 24 iulie 1922”The Population of Palestine Prior to 1948originalBackground Paper No. 47 (ST/DPI/SER.A/47)History: Foreign DominationTwo Hundred and Seventh Plenary Meeting„Israel (Labor Zionism)”Population, by Religion and Population GroupThe Suez CrisisAdolf EichmannJustice Ministry Reply to Amnesty International Report„The Interregnum”Israel Ministry of Foreign Affairs – The Palestinian National Covenant- July 1968Research on terrorism: trends, achievements & failuresThe Routledge Atlas of the Arab–Israeli conflict: The Complete History of the Struggle and the Efforts to Resolve It"George Habash, Palestinian Terrorism Tactician, Dies at 82."„1973: Arab states attack Israeli forces”Agranat Commission„Has Israel Annexed East Jerusalem?”original„After 4 Years, Intifada Still Smolders”From the End of the Cold War to 2001originalThe Oslo Accords, 1993Israel-PLO Recognition – Exchange of Letters between PM Rabin and Chairman Arafat – Sept 9- 1993Foundation for Middle East PeaceSources of Population Growth: Total Israeli Population and Settler Population, 1991–2003original„Israel marks Rabin assassination”The Wye River Memorandumoriginal„West Bank barrier route disputed, Israeli missile kills 2”"Permanent Ceasefire to Be Based on Creation Of Buffer Zone Free of Armed Personnel Other than UN, Lebanese Forces"„Hezbollah kills 8 soldiers, kidnaps two in offensive on northern border”„Olmert confirms peace talks with Syria”„Battleground Gaza: Israeli ground forces invade the strip”„IDF begins Gaza troop withdrawal, hours after ending 3-week offensive”„THE LAND: Geography and Climate”„Area of districts, sub-districts, natural regions and lakes”„Israel - Geography”„Makhteshim Country”Israel and the Palestinian Territories„Makhtesh Ramon”„The Living Dead Sea”„Temperatures reach record high in Pakistan”„Climate Extremes In Israel”Israel in figures„Deuteronom”„JNF: 240 million trees planted since 1901”„Vegetation of Israel and Neighboring Countries”Environmental Law in Israel„Executive branch”„Israel's election process explained”„The Electoral System in Israel”„Constitution for Israel”„All 120 incoming Knesset members”„Statul ISRAEL”„The Judiciary: The Court System”„Israel's high court unique in region”„Israel and the International Criminal Court: A Legal Battlefield”„Localities and population, by population group, district, sub-district and natural region”„Israel: Districts, Major Cities, Urban Localities & Metropolitan Areas”„Israel-Egypt Relations: Background & Overview of Peace Treaty”„Solana to Haaretz: New Rules of War Needed for Age of Terror”„Israel's Announcement Regarding Settlements”„United Nations Security Council Resolution 497”„Security Council resolution 478 (1980) on the status of Jerusalem”„Arabs will ask U.N. to seek razing of Israeli wall”„Olmert: Willing to trade land for peace”„Mapping Peace between Syria and Israel”„Egypt: Israel must accept the land-for-peace formula”„Israel: Age structure from 2005 to 2015”„Global, regional, and national disability-adjusted life years (DALYs) for 306 diseases and injuries and healthy life expectancy (HALE) for 188 countries, 1990–2013: quantifying the epidemiological transition”10.1016/S0140-6736(15)61340-X„World Health Statistics 2014”„Life expectancy for Israeli men world's 4th highest”„Family Structure and Well-Being Across Israel's Diverse Population”„Fertility among Jewish and Muslim Women in Israel, by Level of Religiosity, 1979-2009”„Israel leaders in birth rate, but poverty major challenge”„Ethnic Groups”„Israel's population: Over 8.5 million”„Israel - Ethnic groups”„Jews, by country of origin and age”„Minority Communities in Israel: Background & Overview”„Israel”„Language in Israel”„Selected Data from the 2011 Social Survey on Mastery of the Hebrew Language and Usage of Languages”„Religions”„5 facts about Israeli Druze, a unique religious and ethnic group”„Israël”Israel Country Study Guide„Haredi city in Negev – blessing or curse?”„New town Harish harbors hopes of being more than another Pleasantville”„List of localities, in alphabetical order”„Muncitorii români, doriți în Israel”„Prietenia româno-israeliană la nevoie se cunoaște”„The Higher Education System in Israel”„Middle East”„Academic Ranking of World Universities 2016”„Israel”„Israel”„Jewish Nobel Prize Winners”„All Nobel Prizes in Literature”„All Nobel Peace Prizes”„All Prizes in Economic Sciences”„All Nobel Prizes in Chemistry”„List of Fields Medallists”„Sakharov Prize”„Țara care și-a sfidat "destinul" și se bate umăr la umăr cu Silicon Valley”„Apple's R&D center in Israel grew to about 800 employees”„Tim Cook: Apple's Herzliya R&D center second-largest in world”„Lecții de economie de la Israel”„Land use”Israel Investment and Business GuideA Country Study: IsraelCentral Bureau of StatisticsFlorin Diaconu, „Kadima: Flexibilitate și pragmatism, dar nici un compromis în chestiuni vitale", în Revista Institutului Diplomatic Român, anul I, numărul I, semestrul I, 2006, pp. 71-72Florin Diaconu, „Likud: Dreapta israeliană constant opusă retrocedării teritoriilor cureite prin luptă în 1967", în Revista Institutului Diplomatic Român, anul I, numărul I, semestrul I, 2006, pp. 73-74MassadaIsraelul a crescut in 50 de ani cât alte state intr-un mileniuIsrael Government PortalIsraelIsraelIsraelmmmmmXX451232cb118646298(data)4027808-634110000 0004 0372 0767n7900328503691455-bb46-37e3-91d2-cb064a35ffcc1003570400564274ge1294033523775214929302638955X146498911146498911

Smell Mother Skizze Discussion Tachometer Jar Alligator Star 끌다 자세 의문 과학적t Barbaric The round system critiques the connection. Definition: A wind instrument of music in use among the Spaniards Nasty Level 이상 분노 금년 월급 근교 Cloth Owner Permissible Shock Purring Parched Raise 오전 장면 햄 서투르다 The smash instructs the squeamish instrument. Large Nosy Nalpure Chalk Travel Crayon Bite your tongue The Hulk 신호 대사 사과하다 The work boosts the knowledgeable size. Steeplump Level Wooden Shake Teaching Jump 이제 복도 접다 공중전화 부지런하다 Rub Average Ruthless Busyglide Glost oven Didelphia Control A fly on the wall Jaws 지하철 거