Каков наилучший способ изменить тип значения на ссылочный тип в C #?

1

У меня есть три класса, которые определены следующим образом:

public class Base
{
    public int Id { get; set; }
}

public class Bar : Base { ... }

public class Foo : Base
{
    public int? ParentId { get; set; }
    public Base Parent { get; set; }

    public int? FooParentId { get; set; }
    public Foo FooParent { get; set; }

    public int? BarParentId { get; set; }
    public Bar BarParent { get; set; }

    public Foo(Foo parent)
    {
        FooParent = parent;
        FooParentId = parent.Id;

        Parent = FooParent; // Now changes to Parent are reflected on FooParent
        ParentId = FooParentId; // Changes to ParentId are not reflected because it is a value type.
    }
    public Foo(Bar parent)
    {
        // Same implementation as ctor(Foo parent);
    }
}

То, что я пытаюсь сделать, это Parent ссылка либо FooParent или BarParent (который я считаю, это довольно просто,), а затем ParentId ссылочный FooParentId или BarParentId. Каков самый разумный способ сделать ParentId ссылочным типом?

В ответе здесь упоминается, что бокс/распаковка целого числа имеет множество проблем, связанных с ним.
Это действительно плохое решение?

Редактировать:
Я должен был упомянуть, что Foo и Bar являются таблицами Entity Framework. Foo - это объект, который может быть дочерним для одной или другой таблицы, а для кода Entity Framework - сначала правильно генерировать таблицу, необходимо определить как FooParent и BarParent. Кроме того, ParentId может не ссылаться на Parent в его получателе. Entity Framework тоже виноват в этом. Entity Framework Reinserts Существующие объекты при вызове context.Set<Foo>().Add(newItem); , Все родители, которые не являются нулевыми, повторно вставлены.

Теги:
entity-framework
reference

3 ответа

1
Лучший ответ

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

Например, используя делегат Action<T>, мы можем перенаправить это изменение в ParentId на соответствующий [Foo|Bar]ParentId:

public class Base
{
    public int Id { get; set; }
}

public class Bar : Base {  }

public class Foo : Base
{
    private int? _parentId;

    public int? ParentId { 
        get{ return _parentId; } 
        set{ 
            _parentId = value;
            if( OnParentChangeAction != null ) {
                OnParentChangeAction( _parentId ); 
            }
        } 
    }

    public Base Parent { get; set; }

    public int? FooParentId { get; set; }
    public Foo FooParent { get; set; }

    public int? BarParentId { get; set; }
    public Bar BarParent { get; set; }

    private Action<int?> OnParentChangeAction{ get; set; }

    public Foo(Foo parent)
    {
        FooParent = parent;
        FooParentId = parent.Id;

        Parent = FooParent;
        ParentId = FooParentId;
        OnParentChangeAction = newParentId => FooParentId = newParentId;
    }
    public Foo(Bar parent)
    {
        BarParent = parent;
        BarParentId = parent.Id;

        Parent = BarParent; 
        ParentId = BarParentId; 
        OnParentChangeAction = newParentId => BarParentId = newParentId;
    }
}
  • 0
    То, что у вас есть, это концептуально событие. Вы найдете, что лучше использовать event C # для эмуляции концептуальных событий, чем делегат в качестве свойства.
  • 0
    Почему «лучше» использовать event если вы не используете ни одну из функций, предоставляемых событиями, например многоадресную рассылку? Если бы это была публично выставленная собственность, я бы согласился, но это частный участник, и event излишне.
Показать ещё 3 комментария
0

Вы можете добавить логику для get и set аксессуаров ваших FooParentId и BarParentId, но согласитесь с @Servy, что это плохой дизайн.

И причина состоит не только в том, что у них есть как ID, так и ссылки на объекты. Я не понимаю, зачем вам нужно иметь BarParent и FooParent, просто иметь 1 свойство типа IParent а затем обмениваться данными с ним, используя методы, которые предоставляет этот интерфейс, используя все преимущества наследования и полиморфизма.

0

Поскольку у вас уже есть ссылка на родительский объект, вы можете получить свой идентификатор с свойством:

    public int? ParentId 
    { 
        get
        {
            return Parent != null ? Parent.Id : null;
        }
    }
  • 0
    Это отличное предложение, но, к сожалению, оно не сработает для меня. Entity Framework требует, чтобы ParentId был отделен от родительской ссылки. Это объясняется более подробно здесь .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню