Extract common properties of a class

A

Arial

I have more classes with several common properties.

e.g.

class A
{
string Class_A_Prop1{get; set;}
string Class_A_Prop2{get; set;}

string CommonProp1{get; set;} // common to all classes
string CommonProp2{get; set;}
}

class B
{
string Class_B_Prop1{get; set;}
string Class_B_Prop2{get; set;}

string CommonProp1{get; set;} // common to all classes
string CommonProp2{get; set;}
}

i want to write generic method (without using reflection)
which will display properties CommonPorp1 and CommonProp2

something like this

void DisplayCommon<T>(T entity)
{

string p1=entity.CommonProp1;
string p2 = entity.CommonProp2;

Console.WriteLine("{0} {1}",p1,p2);
}

keep in mind that class A & B are generated by a external tool
and I do not want to alter them in any way,
so forget solutions that are using abstract classes, inheritance and
interfaces

is this possible in C# using generics or anonymous types?
 
J

Jon Skeet [C# MVP]

Arial said:
I have more classes with several common properties.

keep in mind that class A & B are generated by a external tool
and I do not want to alter them in any way,
so forget solutions that are using abstract classes, inheritance and
interfaces

is this possible in C# using generics or anonymous types?

No. If there's no interface which explains that A.CommonProp1 and
B.CommonProp1 are linked, you'll have to use reflection.
 
M

Marc Gravell

keep in mind that class A & B are generated by a external tool

Are they (or could they be) declared as partial classes? If this was
"partial class A" etc, then you could use a *second* code file to make
A & B implement a common interface:

interface IFoo {...} // common members
partial class A : IFoo {}
partial class B : IFoo {}

And let implicit interface implementation deal with the rest (assuming
the properties etc are public). Then your external tool doesn't ever
know about IFoo.

If this isn't an option, then reflection is your only choice.

Marc
 
A

Arial

Marc Gravell said:
Are they (or could they be) declared as partial classes? If this was
"partial class A" etc, then you could use a *second* code file to make
A & B implement a common interface:

interface IFoo {...} // common members
partial class A : IFoo {}
partial class B : IFoo {}

And let implicit interface implementation deal with the rest (assuming
the properties etc are public). Then your external tool doesn't ever
know about IFoo.

If this isn't an option, then reflection is your only choice.

Marc

Very clever idea Marc.



In fact those files are generated by SQLMetal.

and common properties represents fields from db which are the same in every
table

e.g.(LastChangedTime).



The problem is that there are a lot of those classes, and reflection seems
to be only painless and satisfactory solution in my case.



Anyway I appreciate your wise answer.
 
M

Marc Gravell

In that case, simply specify the interface name as the base-class; for
dbml files this is an entry in the xml file. At the command line, this
is /entitybase

I use *exactly* this (the dbml version) to define a common audit
interface (who/when created/updated), and I override the
GetChangeSet() [or something] so that the "who" gets updated
automatically to the current user (using the thread's principal).

Marc
 
M

Marc Gravell

Sorry, it is SubmitChanges:

/// <summary>
/// Sends changes that were made to retrieved objects to the
underlying database,
/// and specifies the action to be taken if the submission
fails.
/// </summary>
/// <param name="failureMode">The action to be taken if the
submission fails. Valid arguments are as
follows:System.Data.Linq.ConflictMode.FailOnFirstConflictSystem.Data.Linq.ConflictMode.ContinueOnConflict</
param>
public override void
SubmitChanges(System.Data.Linq.ConflictMode failureMode)
{
// Set audit columns correctly
ChangeSet delta = GetChangeSet();

IPrincipal principal = Thread.CurrentPrincipal;
IIdentity identity = principal == null ? null :
principal.Identity;
string name = identity == null ? null : identity.Name;
if (string.IsNullOrEmpty(name)) name =
Environment.MachineName;

foreach (IEntityChangeAudit ins in
delta.Inserts.OfType<IEntityChangeAudit>())
{
ins.CreatedBy = ins.UpdatedBy = name;
ins.DateCreated = ins.LastUpdated = DateTime.Now;
}
foreach (IEntityChangeAudit upd in
delta.Updates.OfType<IEntityChangeAudit>())
{
upd.UpdatedBy = name;
upd.LastUpdated = DateTime.Now;
}
base.SubmitChanges(failureMode);
}

Marc
 
A

Arial

Marc Gravell said:
In that case, simply specify the interface name as the base-class; for
dbml files this is an entry in the xml file. At the command line, this
is /entitybase

I use *exactly* this (the dbml version) to define a common audit
interface (who/when created/updated), and I override the
GetChangeSet() [or something] so that the "who" gets updated
automatically to the current user (using the thread's principal).

Marc

Tnx a lot!
That is exactley what I need.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top