If what you want is this, then check out the code at the bottom.
It's written in Oxygene[1], hope that's not a problem.
[1]or Delphi Prism how it's called now
var inst1 := new Sample();
var inst2 := new Sample(X := 2);
var test1 := new DefaultValueInspector<Sample>(true);
var test2 := new DefaultValueInspector<Sample>(inst2, true);
var d := test1.DefaultValueByName["X"];
var inst1HasDefault := test1.HasDefaultValue(inst1, "X");
var inst2HasDefault := test1.HasDefaultValue(inst2, "X");
Console.WriteLine("Value: {0}; inst1HasDefault: {1}; inst2HasDefault {2}",
d, inst1HasDefault, inst2HasDefault);
d := test2.DefaultValueByName["X"];
inst1HasDefault := test2.HasDefaultValue(inst1, "X");
inst2HasDefault := test2.HasDefaultValue(inst2, "X");
Console.WriteLine("Value: {0}; inst1HasDefault: {1}; inst2HasDefault {2}",
d, inst1HasDefault, inst2HasDefault);
Output:
Value: 1; inst1HasDefault: True; inst2HasDefault False
Value: 2; inst1HasDefault: False; inst2HasDefault True
uses
System.Collections.Generic,
System.Reflection;
type
DefaultValueInspector<T> = public class
private
method get_DefaultValueByName(memberName : String): Object;
method get_DefaultValueByMember(memberInfo : MemberInfo) : Object;
protected
class method GetMemberErrorMessage(memberName : String) : String;
method GetMember(memberName : String) : MemberInfo;
property MembersByName : Dictionary<String, MemberInfo>
:= new Dictionary<String, MemberInfo>(); readonly;
property GettersByMember : Dictionary<MemberInfo, Converter<T, Object>>
:= new Dictionary<MemberInfo, Converter<T, Object>>(); readonly;
property DefaultValuesByMember : Dictionary<MemberInfo, Object>
:= new Dictionary<MemberInfo, Object>(); readonly;
public
property UseHiddenMembers : Boolean; readonly;
property DefaultValueByName[memberName : String] : Object
read get_DefaultValueByName;
property DefaultValueByMember[memberInfo : MemberInfo] : Object
read get_DefaultValueByMember;
method GetGetMethod(memberName : String) : Converter<T, Object>;
method GetGetMethod(memberInfo : MemberInfo) : Converter<T, Object>;
method HasDefaultValue(instance : T; memberName : String) : Boolean;
method HasDefaultValue(instance : T; memberInfo : MemberInfo) : Boolean;
constructor(useHiddenMembers : Boolean);
constructor(defaultInstance : T; useHiddenMembers : Boolean);
end;
implementation
constructor DefaultValueInspector<T>(useHiddenMembers : Boolean);
begin
var ctorInfo := typeOf(T).GetConstructor([]);
constructor(ctorInfo.Invoke([]) as T, useHiddenMembers);
end;
constructor DefaultValueInspector<T>(defaultInstance : T; useHiddenMembers : Boolean);
begin
var bf := iif(useHiddenMembers,
BindingFlags.NonPublic)
or BindingFlags.Public
or BindingFlags.Instance;
for mi in typeOf(T).GetMembers(bf) do
case mi.MemberType of
MemberTypes.Field :
with matching fi := FieldInfo(mi) do
begin
MembersByName.Add(fi.Name, fi);
GettersByMember.Add(mi, obj -> fi.GetValue(obj));
end;
MemberTypes.Property :
with matching pi := PropertyInfo(mi) do
if pi.GetIndexParameters().Length = 0 then
begin
MembersByName.Add(pi.Name, pi);
GettersByMember.Add(mi, obj -> pi.GetValue(obj, nil));
end;
end;
for g in GettersByMember do
with val := g.Value(DefaultInstance) do
if assigned(val) then
DefaultValuesByMember.Add(g.Key, val);
end;
class method DefaultValueInspector<T>.GetMemberErrorMessage(memberName : String) : String;
begin
exit "The member '" + memberName + "' does not exist in type " + typeOf(T).FullName
+ " or it has indexers."
end;
method DefaultValueInspector<T>.get_DefaultValueByName(memberName : String): Object;
begin
var mi := GetMember(memberName);
DefaultValuesByMember.TryGetValue(mi, out result);
end;
method DefaultValueInspector<T>.get_DefaultValueByMember(memberInfo : MemberInfo) : Object;
begin
if not DefaultValuesByMember.TryGetValue(memberInfo, out result) then
raise new ArgumentException(GetMemberErrorMessage(memberInfo.Name),
"memberName");
end;
method DefaultValueInspector<T>.GetGetMethod(memberName : String) : Converter<T, Object>;
begin
var mi := GetMember(memberName);
exit GetGetMethod(mi);
end;
method DefaultValueInspector<T>.GetGetMethod(memberInfo : MemberInfo) : Converter<T, Object>;
begin
if not GettersByMember.TryGetValue(memberInfo, out result) then
raise new ArgumentException(GetMemberErrorMessage(memberInfo.Name),
"memberName");
end;
method DefaultValueInspector<T>.GetMember(memberName : String) : MemberInfo;
begin
if not MembersByName.TryGetValue(memberName, out result) then
raise new ArgumentException(GetMemberErrorMessage(memberName),
"memberName");
end;
method DefaultValueInspector<T>.HasDefaultValue(instance : T; memberName : String) : Boolean;
begin
var getter := GetGetMethod(memberName);
var instanceValue := getter(instance);
exit Equals(DefaultValueByName[memberName], instanceValue);
end;
method DefaultValueInspector<T>.HasDefaultValue(instance : T; memberInfo : MemberInfo) : Boolean;
begin
var getter := GetGetMethod(memberInfo);
var instanceValue := getter(instance);
exit Equals(DefaultValueByMember[memberInfo], instanceValue);
end;