限制对部分类

时间:2016-08-26 01:52:16

标签: c# .net visual-studio

上下文

我有一个自动生成的分部类,其中一些公共属性表示来自其他嵌套模型的数据。例如。一个有床的房间:

// Auto-generated class from DB schema
public partial class HotelRoom : BaseModel
{
    public int RoomNumber {get; set;}
    public string BedKind {get; set;}
    public int BedSize {get; set;}
    public bool BedHasBlankets {get; set;}

    // Methods and more DB-related logic here
}

问题

我想在单个对象中封装嵌套模型的数据(在本例中为 Bed ),但限制对容器模型中表示它的属性的访问(的空房)。

// Suppose we get a reference to a HotelRoom
HotelRoom room = HotelRoom.GetFromDB(someNumber);

// I want this to be valid ...
var size = room.Bed.Size;

// ...but this to be invalid
var size = room.BedSize;

无效我的意思是我希望它导致编译错误,但如果根本不可能,发出警告,甚至阻止BedSize出现在IntelliSense中(例如使用{时) {3}}属性)可能几乎和我想要的一样好。

我目前的做法

目前,我可以使用嵌套类实现此目的,但我希望代码禁止或至少警告程序员不要使用某些自动生成的公共属性。 E.g。

// My own partial class
public partial class HotelRoom : BaseModel
{
    // Here I would like to make BedKind, BedSize and BedHasBlankets private
    // or make something that has a similar effect as making them private

    // Then I can encapsulate those variables in this object whose class
    // has access to the private properties of HotelRoom, since it's nested
    private Bed bed;
    public Bed Bed
    {
      get
      {
        if(bed == null)
        {
          bed = new Bed(this);
        }
        return bed;
      }
    }

    public class Bed
    {
      private HotelRoom container;
      public string Kind { get{ return container.BedKind } }
      public int Size { get{ return container.BedSize } }
      // Maybe perform some data transformation:
      public bool NeedsBlankets { get{ return !container.BedHasBlankets;} }

      public Bed(HotelRoom container)
      {
        this.container = container
      }
}

为什么我要这个?

我知道你可能在想为什么我会想要这样的东西。好吧,在我的现实生活场景中,一些自动生成的公共属性的名称并不像room.BedSize那样简短直观,而是像obj.DeviceManufacturerManufacturerTypeId这样的东西,我认为可以更清楚地调用使用像obj.Manufacurer.TypeId这样的东西。

TL; DR:

如何在部分类中将某些属性设置为私有,这些属性在同一个分类的另一个(自动生成的)部分中定义为public? 如果那是不可能的,我怎样才能达到类似的效果?

2 个答案:

答案 0 :(得分:1)

将自动生成的类程序的用户设置为其界面。而不是暴露类本身,暴露它的接口,并只放置你想要公开的方法:

interface IBed {
    string Kind {get; set;}
    int Size {get; set;}
    bool HasBlankets {get; set;}
}
interface IHotelRoom {
    int RoomNumber {get; set;}
    IBed Bed {get;}
}
partial class HotelRoom : BaseModel, IHotelRoom {
    private class Bed : IBed {
        private HotelRoom room;
        internal Bed(HotelRoom room) {this.room = room;}
        public string Kind {
            get { return room.BedKind; }
            set { room.BedKind = value; }
        }
        ...
    }
    public IBed Bed {get;} = new Bed(this);
}

只要用户获得IHotelRom个对象,而不是HotelRoom,他们就无法在没有明确演员的情况下访问HotelRoom的公共属性。

答案 1 :(得分:0)

一种方法可能是使自动生成的属性显式实现接口,该接口仅暴露给需要这些属性的代码。例如:

interface IPersistableHotelRoom { 
    int BedSize {get; set;}
}

public class HotelRoom : IPersistableHotelRoom {
    int IPersistableHotelRoom.BedSize { get; set; }

    public class Bed {
        private HotelRoom room; // set this in the nested class constructor, not shown
        public int Size { get { return room.BedSize; } }
    }

    public Bed Bed {get;}

    public HotelRoom() {
        this.Bed = new Bed(this);
    }
}

在上面的代码中(未经过测试,但应该有效),无法访问IPersistableHotelRoom的代码永远不会看到在那里定义的属性。 可以访问它的代码可以通过强制转换为IPersistableHotelRoom来访问这些属性:

var foo = ((IPersistableHotelRoom)hotelRoom).BedSize;