简体   繁体   English

C#中的条件变量范围

[英]Conditional Variable Scope in C#

So this is kind of an odd question, is there any way to modify a variable's visibility depending on a certain condition (eg via some attribute)? 因此,这是一个奇怪的问题,是否有任何方法可以根据特定条件(例如,通过某些属性)来修改变量的可见性?

This may be more of a design pattern question, so allow me to explain my situation: 这可能更多是设计模式问题,所以请允许我解释一下我的情况:

I have a class which has many user configurable values (9 total, 4 of which are conditional). 我有一个具有许多用户可配置值的类(总共9个,其中4个是有条件的)。 However, some of these variables only apply if certain conditions are met. 但是,其中一些变量仅在满足某些条件时适用。 Right now, they are all visible to the user. 现在,它们对用户都是可见的。 I'm looking for a way I can restrict the visibility of certain variables at compile time in a per-scope context. 我正在寻找一种方法,可以在每个作用域的上下文中在编译时限制某些变量的可见性。 I want to avoid getting the user confused and having them potentially set certain values that will just get ignored. 我想避免让用户感到困惑,并避免他们潜在地设置某些将被忽略的值。

Example: 例:

Property B only applies if property A is true . 属性B仅在属性Atrue If the user sets A to false , the current scope will lose visibility of B . 如果用户将A设置为false ,则当前作用域将失去B可见性。

var settings = new Settings() {
    A = true,
    B = ... //Everything is fine since A is true
}


var settings = new Settings() {
    A = false,
    B = ... //Compile Error, Settings does not contain definition for "B"
}

//Somewhere that uses the settings variable...
if(A) { useB(B); } else { useDefault(); }

Is there a better solution to this than "good documentation?" 有比“好的文档”更好的解决方案吗?

You can't do exactly what you're asking, but you can get something close chaining fluent APIs with the builder pattern... 您不能完全按照自己的要求进行操作,但是可以使用构建器模式将流利的API紧密链接起来……

public interface ISettings
{
    string SomePropertyOnlyForTrue { get; }
    int B { get; }
}

public interface IBuilderFoo
{
    IBuilderFooTrue BuildFooTrue();
    IBuilderFooFalse BuildFooFalse();
}

public interface IBuilderFooTrue
{
    IBuilderFooTrue WithSomePropertyOnlyForTrue(string value);
    ISettings Build();
}

public interface IBuilderFooFalse
{
    IBuilderFooFalse WithB(int value);
    ISettings Build();
}

public void Whatever()
{
    var theThingTrue = new BuilderFoo().BuildFooTrue()
        .WithSomePropertyOnlyForTrue("face").Build();
    var theThingTrueCompilerError = new BuilderFoo().BuildFooTrue()
        .WithB(5).Build(); // compiler error

    var theThingFalse = new BuilderFoo().BuildFooFalse()
        .WithB(5).Build();
    var theThingFalseCompilerError = new BuilderFoo().BuildFooFalse()
        .WithSomePropertyOnlyForTrue("face").Build(); // compiler error
}

Note the getters are only defined in the ISettings , you'd be best to make the class immutable to not allow changing after being Build() . 请注意,getter仅在ISettings定义,您最好使该类不可变,以使其在Build()之后不允许更改。 I did not provide impls for the builders, but should be easy enough to figure out. 我没有为建造者提供提示,但应该足够容易找出。 Let me know if you do need something aside from the builder samples like at https://www.dofactory.com/net/builder-design-pattern . 让我知道您是否确实需要构建器示例以外的内容,例如https://www.dofactory.com/net/builder-design-pattern

Here's a quick example: https://dotnetfiddle.net/DtEidh 这是一个简单的示例: https : //dotnetfiddle.net/DtEidh

No, this is not possible. 不,这是不可能的。 If it's some kind of security question, note if you want to go crazy, you can even call internal things via reflection 如果是某种安全问题,请注意,如果您想发疯,甚至可以通过反射来调用internal事物

The closest thing I can imagine is with interfaces: 我能想到的最接近的东西是接口:

public interface IA
{
    public bool A { get; set; }
}

public interface IB
{
    public bool B { get; set; }
}

public class Settings: IA, IB
{
    public bool A { get; set; }
    public bool B { get; set; }
}

Usage for example: 用法例如:

IA config = new Settings();
config.A = true; //fine
config.B = true; //error

That said, if this is a problem, your Model probably contains to much data. 就是说,如果这是一个问题,则您的模型可能包含很多数据。 Maybe A and B could be seperate classes, which are properties of your model? 也许AB可以是单独的类,它们是模型的属性?

public class Settings
{
    public A A {get; set;}
    public B B {get; set;}
}

Or you could create a factory class 或者您可以创建工厂类

public class SettingsFactory
{
    public Settings CreateA(...)
    {
        return new Settings { ... };
    }

    public Settings CreateB(...)
    {
        return new Settings { ... };
    }
}

Anyway, you should trust your user, that he is reading your documentation. 无论如何,您应该信任您的用户,他正在阅读您的文档。

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

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