Защитить коллекции поиска и элементы от редактирования

Я не хочу, чтобы что-нибудь из этого было редактируемым вообще. Для коллекций кажется совершенно прозрачным использование ReadOnlyCollection (хотя я не знаю, является ли это хорошим способом всегда создавать новую коллекцию ReadOnlyCollection из коллекции (это дорого?)).

public static class Lookups
{
    private static Collection<MyBusinessObject> businessObjects;
    // [...]

    public static ReadOnlyCollection<MyBusinessObjects> BusinessObjects
    {
        get
        {
            return new ReadOnlyCollection<MyBusinessObject>(businessObjects);
        }
    }
    // [...]
}

Но более важно: что мне делать с предметами внутри коллекций? Я хочу, чтобы этот тест прошел какие-либо идеи?

    [TestMethod]
    public void Items_Should_Not_Be_Editable()
    {
        var businessObject = Lookups.BusinessObjects.First();

        businessObject.Id = 1337;

        Assert.AreNotEqual(1337, Lookups.BusinessObjects.First().Id);
    }

2 ответа

Решение

При использовании ReadonlyCollection вам не нужно каждый раз создавать новый экземпляр. Альтернатива - выставить IEnumerable, так как он доступен только для чтения. Readonlycollection предлагает более сильную защиту, как можно увидеть здесь.

Экземпляр универсального класса ReadOnlyCollection всегда доступен только для чтения. Коллекция, доступная только для чтения, - это просто коллекция с оболочкой, которая предотвращает изменение коллекции; поэтому, если изменения сделаны в основной коллекции, коллекция только для чтения отражает эти изменения. Смотрите коллекцию для модифицируемой версии этого класса.

[Test]
public void TestNameTest()
{
    var names = new List<string>() {"Johan", "Tkrause"};
    var readOnlyCollection = new ReadOnlyCollection<string>(names);
    names.Add("Lars");
    Assert.AreEqual(3,readOnlyCollection.Count);
}

В твоем случае:

private List<IMyBusinessObjectType> _businessObjects= new List<IMyBusinessObjectType>();
private ReadOnlyCollection<IMyBusinessObjectType> _readOnlybusinessObjects;
public ReadOnlyCollection<IMyBusinessObjectType> BusinessObjects
{
    get
    {
        if(_readOnlybusinessObjects==null)
            _readOnlybusinessObjects=new ReadOnlyCollection<IMyBusinessObjectType>(_businessObjects);
        return _readOnlybusinessObjects;
    }
}
public interface IMyBusinessObjectType
{
    string Name { get; }
}

public class MyBusinessObjectType : IMyBusinessObjectType
{
    public string Name { get; set; }
}

Что касается бизнес-объектов, они могут иметь частные сеттеры или реализовывать интерфейс только для чтения, как было предложено Ларсом.

Вы должны наследовать MyBusinessObject от интерфейса и выставить это.

internal class MyBusinessObject : IMyBusinessObject {
    public string Id { get; set; }
}

public interface IMyBusinessObject {
    public string Id { get; }
}

А затем выставьте этот интерфейс в коллекцию MyCollection.

Может быть, сделать то же самое для коллекции и не выставлять методы добавления, удаления и т. Д.

Другие вопросы по тегам