繁体   English   中英

C#:内部和公共接口,自动实现的属性,但具有结构…

[英]C#: Internal and public interfaces, auto-implemented properties, but with structs…

我知道有一种模式涉及部分类,以实现一个具有可设置程序集属性的类,但该类从外部是只读的,例如

// This is just the non-working example to get the idea of what I want it to do across

public interface IMyReadable
{
    int Property1 { get; }
    string Property2 { get; }
}

internal interface IMyEditable : IMyReadable
{
    int Property1 { get; set; }
    string Property2 { get; set;}
}

public class Implementation : IMyEditable
{
    public int Property1 { get; internal set; }
    public string Property2 { get; internal set;}
}

因为您无法在界面中定义“内部集”。 可以为诸如https://stackoverflow.com/a/42082500/6155053之类的类实现

…但是如果我想对结构执行此操作怎么办?

我知道,结构通常应该是完全只读的,但是最好有多个不同的结构实现来实现接口,然后能够首先对其进行实例化,然后再从程序集内部按属性初始化它们,例如在工厂类,而不必为每个不同的实现(通过其c'tor或其他东西)写出接口的每个属性的设置。

那会让我做类似的事情

// non-sense, but explanatory code snippet
[…]
var structs = new HashSet<IMyEditable>();
structs.Add(new MyEditableImplementation1());
structs.Add(new MyEditableImplementation2());
structs.Add(new MyEditableImplementation3());

int i = 0;
foreach(IMyEditable s in structs)
{
    s.Property1 = ++i;
    s.Property2 = i.ToString();
}

// ...and still be able to set custom properties only some of the implementations
// have afterwards, etc., and when you then return, for example do:

return structs.Cast<IMyReadable>();

随着接口实现数量的增加,将省去编写很多用于初始化的样板。

但是,由于结构始终是密封的,并且不能从“基本结构”继承……我将如何做到这一点,而又不会失去自动实现属性的优势(如果我要使用具有共享私有字段的代理属性来实现的话)在每个结构中-再次,这意味着很多样板代码,仅在另一个地方)。

这可能吗? 如果是这样,怎么办?

编辑:添加了第二个示例以解释所需的用法

这个怎么样?

在此处输入图片说明

IReader.cs(ClassLibrary1)

namespace ClassLibrary1
{
    public interface IReader
    {
        int Property1 { get; }
        string Property2 { get; }
    }
}

IWriter.cs(ClassLibrary1)

namespace ClassLibrary1
{
    internal interface IWriter : IReader
    {
        new int Property1 { get; set; }
        new string Property2 { get; set; }
    }
}

SomeObject.cs(ClassLibrary1)

namespace ClassLibrary1
{
    internal class SomeObject : IWriter
    {
        public int Property1 { get; set; }
        public string Property2 { get; set; }
    }
}

Worker.cs(ClassLibrary1)

namespace ClassLibrary1
{
    using System.Collections.Generic;
    using System.Linq;

    public static class Worker
    {
        // NOTE: Thanks to internal on the IWriter, you can't return IWriter here.
        public static IEnumerable<IReader> DoSomething()
        {
            var structs = new HashSet<IWriter>();
            structs.Add(new SomeObject());
            structs.Add(new SomeObject());
            structs.Add(new SomeObject());

            int i = 0;
            foreach (IWriter s in structs)
            {
                s.Property1 = ++i;
                s.Property2 = i.ToString();
            }

            return structs.Cast<IReader>();
        }
    }
}

Program.cs(ConsoleApplication3)

namespace ConsoleApplication3
{
    using System.Collections.Generic;
    using System.Linq;
    using ClassLibrary1;

    public class Program
    {
        private static void Main(string[] args)
        {
            // NOTE: You can't cast the structs to IWriter here.
            var structs = Worker.DoSomething();

            // This will not compile:
            // (structs.FirstOrDefault() as IWriter).Property1 = 10
        }
    }
}

注意:

  • IWriterinternal ,这意味着您不能在ClassLibrary1之外传递/使用它。 完美,只有您的“内部人员”可以处理它,而对于外部世界,您只能公开IReader ,这就是我们所做的。
  • 在控制台应用程序中,您无法将对象投射到IWriter 哪个好

有趣的是,“立即窗口”使我可以将结构IWriterIWriter ,但是我认为它使用了反射,并且在编译时不允许这样做,所以您很好!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM