Приведение к универсальному типу в неуниверсальном методе - PullRequest
0 голосов
/ 23 октября 2011

Что я делаю сейчас:

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");
        }
    }
}

Это печатает:

MyIntBO 1008
MyGuidBO
PersistentBO

Я бы хотел напечатать:

MyIntBO 1008
MyGuidBO 6135d49b-81bb-43d4-9b74-dd84c2d3cc29
PersistentBO

Что такоесамый элегантный способ сделать это?

Я хочу поддерживать все типы клавиш - int, long, Guid и т. д., поэтому я бы предпочел не делать несколько приведений.Обратите внимание, что не каждый бизнес-объект реализует этот интерфейс (некоторые не имеют единственного первичного ключа).

Я понимаю, что мог бы использовать отражение и попытаться получить доступ к свойству Id.Мне было интересно, есть ли лучшее решение.

Пояснение: Чтобы ответить на ответы @Acaz Souza и @Petar Ivanov, у нас есть десятки классов, разбросанных по нескольким сборкам, которые уже реализуют IPrimaryKeyed<T>.Я не хочу нарушать их все, продлевая контракт на интерфейс.Если бы я проектировал это с нуля, их решения работали бы.

Ответы [ 3 ]

2 голосов
/ 23 октября 2011

Просто создайте неуниверсальный интерфейс и замените его универсальным абстрактным классом.Затем проверьте интерфейс:

    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;
}
1 голос
/ 23 октября 2011

Использование отражения не кажется плохим способом.

Метод ToString:

// 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();
}  
1 голос
/ 23 октября 2011

Проблема в этой строке:

var keyed = _businessObject as IPrimaryKeyed<int>;

Ваш другой тип не IPrimaryKeyed<int> равен IPrimaryKeyed<Guid>, тогда if (keyed != null) ложно.

Вы можете попробовать сделатьэто:

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"); } }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...