From: Omatase on
On Jan 28, 10:19 pm, Peter Duniho <no.peted.s...(a)no.nwlink.spam.com>
wrote:
> Omatase wrote:
> > [...]
> > The reason I have such a strange requirement is that I'm making a game
> > where I will be keeping track of these numbers and persisting them to
> > a database as a statistic that will be available at some future point
> > to use in formulae.
>
> And what makes that statistic valuable?  Is it really worth convoluting
> the design of the program just to accommodate that goal?  And if the
> statistic is so valuable, why isn't it worthwhile to just go ahead and
> write a per-property implementation, rather than going after some
> harder-to-maintain solution?
>
> It's your program, and I'm not about to try to argue the point.  The
> above are simply some questions that hopefully give you food for thought
> as you head down this path, so that if you do continue to pursue it, you
> at least do so with some confidence that it's worth doing.
>
> Personally, I'm skeptical.  But if everyone always agreed with me, life
> would be pretty boring.  :)
>
> Pete

Thanks for your help!
From: Andy O'Neill on

"Omatase" <omatase(a)gmail.com> wrote in message
news:a89d2fe5-a343-463f-b215-69fceb04ee12(a)r24g2000yqd.googlegroups.com...
<<>>
>The reason I have such a strange requirement is that I'm making a game
where I will be keeping track of these numbers and persisting them to
a database as a statistic that will be available at some future point
to use in formulae.

Are you counting when something or other is done rather than just access to
the property?
Could you use wpf (like) command routing to count the calls to commands
rather than the specific properties?

I can't help but think maybe you're coming at the problem from the wrong
direction somehow,

From: Gregory A. Beamer on
"Omatase" <omatase(a)gmail.com> wrote in message
news:519b396e-263a-4608-99f3-af0f5d527a0f(a)22g2000yqr.googlegroups.com...
> I have a bunch of entity classes with just a whole bunch of properties
> in it. I have to count each time one of these properties is read and
> written to. I was hoping I could implement a pattern that would allow
> me to do that easily so that I didn't have to write custom setters and
> getters for each property (I'm using automatic properties for
> convenience). Does anyone have any idea how I might be able to do this
> easily?
>
> The more I think about it the more it seems unlikely there is any
> other solution. My mind keeps veering toward events when I try to
> decide how I might easily do this but that's definitely not it. This
> post is just hoping there is something I haven't thought of.

I disagree it is not possible. Peter has suggested some ideas that could be
very helpful. The code generation idea is fairly simple. You create the
recipe for the "cookies" and then the oven (generator) and you can repeat
for all entities. You can also adorn source code files by looking at
properties already created with a "code fixer" type of generator.

If you can force people to adjust the object through a framework, you could
also do some creative things with attributes, but I digress. Actually, this
is a lot like the wrapper class idea.

I also question, like Peter, why the number of sets and gets is important.

--
Peace and Grace,
Greg

Twitter: @gbworld
Blog: http://gregorybeamer.spaces.live.com

************************************************
| Think outside the box! |
************************************************

From: Gregory A. Beamer on


"Peter Duniho" <no.peted.spam(a)no.nwlink.spam.com> wrote in message
news:eQLBWKKoKHA.5696(a)TK2MSFTNGP04.phx.gbl...
>
> Personally, I'm skeptical. But if everyone always agreed with me, life
> would be pretty boring. :)

I don't think you are in danger of that with me around. ;-)

Actually, I do agree with you on this one, however. I am sure there is
something deeper, like a missing persistence call (trying to keep the object
in memory and count changes when it is later persisted?), rather than saving
as the person changes it. If it is truly, the guy can change his mind 20
times before saving, why is the knowledge he did that important?

--
Peace and Grace,
Greg

Twitter: @gbworld
Blog: http://gregorybeamer.spaces.live.com

************************************************
| Think outside the box! |
************************************************

From: Arne Vajhøj on
On 28-01-2010 22:33, Omatase wrote:
> I have a bunch of entity classes with just a whole bunch of properties
> in it. I have to count each time one of these properties is read and
> written to. I was hoping I could implement a pattern that would allow
> me to do that easily so that I didn't have to write custom setters and
> getters for each property (I'm using automatic properties for
> convenience). Does anyone have any idea how I might be able to do this
> easily?
>
> The more I think about it the more it seems unlikely there is any
> other solution. My mind keeps veering toward events when I try to
> decide how I might easily do this but that's definitely not it. This
> post is just hoping there is something I haven't thought of.

My suggestion would be to:
- make the properties virtual
- dynamicly generate a wrapper class that does the book keeping

A simple POC is attached below.

Arne

======================

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

using Microsoft.CSharp;

namespace E
{
public class A
{
public virtual int Iv { get; set; }
public virtual string Sv { get; set; }
}
public class B
{
public virtual int Iv { get; set; }
public virtual double Xv { get; set; }
}
public interface IWrapper
{
int CountGets(string prop);
int CountSets(string prop);
}
public class WrapperGen
{
private Dictionary<Type, Type> cache = new Dictionary<Type,
Type>();
private const string nstemp = @"using System;
using E;

namespace WrapperGen
{{
{0}
}}
";
private const string clztemp = @" public class {0} : {1},
IWrapper
{{
{2}
}}
";
private const string fldtemp = @" private {0} del;
";
private const string contemp = @" public {0}({1} del)
{{
this.del = del;
}}
";
private const string proptemp = @" private int cGet{1} = 0;
private int cSet{1} = 0;
public override {0} {1}
{{
get
{{
cGet{1}++;
return del.{1};
}}
set
{{
cSet{1}++;
del.{1} = value;
}}
}}
";
private const string methgettemp = @" public int
CountGets(string prop)
{{
switch(prop)
{{
{0}
default:
throw new ArgumentException(prop + "" is not a
valid property"");
}}
}}
";
private const string lblgettemp = @" case ""{0}"":
return cGet{0};
break;
";
private const string methsettemp = @" public int
CountSets(string prop)
{{
switch(prop)
{{
{0}
default:
throw new ArgumentException(prop + "" is not a
valid property"");
}}
}}
";
private const string lblsettemp = @" case ""{0}"":
return cSet{0};
break;
";
private Type Create(Type t)
{
StringBuilder sb = new StringBuilder();
StringBuilder sbget = new StringBuilder();
StringBuilder sbset = new StringBuilder();
string clznam = t.Name + "Wrapper";
sb.Append(String.Format(fldtemp, t.Name));
sb.Append(String.Format(contemp, clznam, t.Name));
foreach(PropertyInfo p in t.GetProperties())
{
sb.Append(String.Format(proptemp, p.PropertyType.Name,
p.Name));
sbget.Append(String.Format(lblgettemp, p.Name));
sbset.Append(String.Format(lblsettemp, p.Name));
}
sb.Append(String.Format(methgettemp, sbget.ToString()));
sb.Append(String.Format(methsettemp, sbset.ToString()));
string src = String.Format(nstemp, String.Format(clztemp,
clznam, t.Name, sb.ToString()));
CodeDomProvider comp = new CSharpCodeProvider();
CompilerParameters param = new CompilerParameters();
param.GenerateInMemory = true;
param.ReferencedAssemblies.Add("System.dll");

param.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
CompilerResults res = comp.CompileAssemblyFromSource(param,
src);
if(res.Errors.Count > 0)
{
Console.WriteLine(src);
foreach(CompilerError ce in res.Errors)
{
Console.WriteLine(ce);
}
}
Assembly asm = res.CompiledAssembly;
return asm.GetType("WrapperGen." + clznam);
}
public T Get<T>(T o) where T : class
{
if(!cache.ContainsKey(o.GetType()))
{
cache.Add(o.GetType(), Create(o.GetType()));
}
return (T)cache[o.GetType()].GetConstructor(new Type[] {
o.GetType() }).Invoke(new object[] { o });
}
}
public class Program
{
public static void Main(string[] args)
{
WrapperGen wg = new WrapperGen();
A a = wg.Get(new A());
a.Iv = a.Iv + 1;
a.Sv = "X";
Console.WriteLine(((IWrapper)a).CountGets("Iv") + " " +
((IWrapper)a).CountSets("Iv"));
Console.WriteLine(((IWrapper)a).CountGets("Sv") + " " +
((IWrapper)a).CountSets("Sv"));
B b = wg.Get(new B());
b.Iv = 77;
for(int i = 0; i < 10; i++)
{
int v = b.Iv;
}
Console.WriteLine(((IWrapper)b).CountGets("Iv") + " " +
((IWrapper)b).CountSets("Iv"));
Console.WriteLine(((IWrapper)b).CountGets("Xv") + " " +
((IWrapper)b).CountSets("Xv"));
}
}
}