Reputation: 25523
What I'm doing now:
void Main()
{
var command1 = new PersistenceCommand(new MyIntBO());
var command2 = new PersistenceCommand(new MyGuidBO());
var command3 = new PersistenceCommand(new PersistentBO());
Console.WriteLine(command1.ToString());
Console.WriteLine(command2.ToString());
Console.WriteLine(command3.ToString());
}
public class PersistenceCommand
{
public PersistenceCommand(PersistentBO businessObject)
{
_businessObject = businessObject;
}
public override string ToString()
{
string result = _businessObject.GetType().Name;
var keyed = _businessObject as IPrimaryKeyed<int>;
if (keyed != null)
{
result += " " + keyed.Id.ToString();
}
return result;
}
private readonly PersistentBO _businessObject;
}
public interface IPrimaryKeyed<out TKey>
{
TKey Id { get; }
}
public class PersistentBO {}
public class MyIntBO : PersistentBO, IPrimaryKeyed<int>
{
public int Id { get { return 1008; } }
}
public class MyGuidBO : PersistentBO, IPrimaryKeyed<Guid>
{
public Guid Id
{
get
{
return new Guid("6135d49b-81bb-43d4-9b74-dd84c2d3cc29");
}
}
}
This prints:
MyIntBO 1008 MyGuidBO PersistentBO
I'd like it to print:
MyIntBO 1008 MyGuidBO 6135d49b-81bb-43d4-9b74-dd84c2d3cc29 PersistentBO
What's the most elegant way to do that?
I want to support all types of keys - int
, long
, Guid
, etc. - so I'd rather not do multiple casts. Note that not every business object implements that interface (some do not have a single primary key).
I realize I could use reflection and try to access the Id
property. I was wondering if there's a better solution.
Clarification: To address @Acaz Souza and @Petar Ivanov's answers, we have dozens of classes scattered over multiple assemblies that already implement IPrimaryKeyed<T>
. I do not want to break all of them by extending the interface contract. If I were designing this from scratch, their solutions would work.
Upvotes: 0
Views: 307
Reputation: 7121
Using reflection doesn't seem like a bad way to go here.
ToString method:
// for getting the Id prop
var identProp = _businessObject.GetType().GetProperty("Id");
string result = _businessObject.GetType().Name;
if (identProp != null)
{
result += " " + identProp.GetValue(_businessObject, null).ToString();
}
Upvotes: 1
Reputation: 8631
The problem is in that line:
var keyed = _businessObject as IPrimaryKeyed<int>;
Your other type is not IPrimaryKeyed<int>
is IPrimaryKeyed<Guid>
, then the if (keyed != null)
is false.
You can try do this:
static void Main()
{
var command1 = new PersistenceCommand(new MyIntBO());
var command2 = new PersistenceCommand(new MyGuidBO());
var command3 = new PersistenceCommand(new PersistentBO());
Console.WriteLine(command1.ToString());
Console.WriteLine(command2.ToString());
Console.WriteLine(command3.ToString());
Console.ReadLine();
}
public class PersistenceCommand
{
public PersistenceCommand(PersistentBO businessObject)
{
_businessObject = businessObject;
}
public override string ToString()
{
string result = _businessObject.GetType().Name;
var keyed = _businessObject as IPrimaryKeyed;
if (keyed != null)
{
result += " " + keyed.Id.ToString();
}
return result;
}
private readonly PersistentBO _businessObject;
}
public interface IPrimaryKeyed
{
object Id { get; }
}
public class PersistentBO { }
public class MyIntBO : PersistentBO, IPrimaryKeyed
{
public object Id { get { return 1008; } }
}
public class MyGuidBO : PersistentBO, IPrimaryKeyed
{
public object Id { get { return new Guid("6135d49b-81bb-43d4-9b74-dd84c2d3cc29"); } }
}
Upvotes: 1
Reputation: 93030
Just create a non-generic interface and replace the generic one with generic abstract class. Then check for the interface:
public interface IPrimaryKeyed
{
object ObjId { get; }
}
public abstract class PrimaryKeyed<TKey> : IPrimaryKeyed
{
public object ObjId { get { return Id; } }
public abstract TKey Id { get; }
}
---
public override string ToString()
{
string result = _businessObject.GetType().Name;
var keyed = _businessObject as IPrimaryKeyed;
if (keyed != null)
{
result += " " + keyed.ObjId.ToString();
}
return result;
}
Upvotes: 2