是否有一种优雅的方法可以让类中的每个方法都以C#中的某个代码块开头?

时间:2015-07-01 05:35:46

标签: c#

我有一个类,每个方法都以相同的方式启动:

  <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/popup_element"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#333333"
android:gravity="center"
android:orientation="vertical"
tools:ignore="ButtonStyle" >

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <TextView
            android:id="@+id/textView6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="choose_emotion"
            android:textColor="@color/white"
            android:textSize="20sp" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="15dp"
            android:gravity="center"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/emo_sad"
                android:layout_width="83dp"
                android:layout_height="83dp"
                android:layout_marginEnd="5dp"
                android:layout_marginRight="5dp"
                android:background="@drawable/ic_launcher"
                android:text="emo_sad"
                android:textColor="@color/white"
                android:textSize="12sp" />

            <Button
                android:id="@+id/emo_happy"
                android:layout_width="83dp"
                android:layout_height="83dp"
                android:background="@drawable/ic_launcher"
                android:text="emo_happy"
                android:textColor="@color/white"
                android:textSize="12sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="5dp"
            android:gravity="center"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/emo_depressed"
                android:layout_width="83dp"
                android:layout_height="83dp"
                android:background="@drawable/ic_launcher"
                android:text="emo_depressed"
                android:textColor="@color/white"
                android:textSize="12sp" />

            <Button
                android:id="@+id/emo_question"
                android:layout_width="83dp"
                android:layout_height="83dp"
                android:layout_margin="8dp"
                android:background="@drawable/ic_launcher"
                android:textColor="@color/white"
                android:textSize="12sp" />

            <Button
                android:id="@+id/emo_anxious"
                android:layout_width="83dp"
                android:layout_height="83dp"
                android:background="@drawable/ic_launcher"
                android:text="emo_anxious"
                android:textColor="@color/white"
                android:textSize="12sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:gravity="center"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/emo_neutral"
                android:layout_width="83dp"
                android:layout_height="83dp"
                android:layout_marginEnd="5dp"
                android:layout_marginRight="5dp"
                android:background="@drawable/ic_launcher"
                android:text="emo_neutral"
                android:textColor="@color/white"
                android:textSize="12sp" />

            <Button
                android:id="@+id/emo_angry"
                android:layout_width="83dp"
                android:layout_height="83dp"
                android:background="@drawable/ic_launcher"
                android:text="emo_angry"
                android:textColor="@color/white"
                android:textSize="12sp" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:orientation="horizontal" >

            <Button
                android:id="@+id/btn_done_popup"
                android:layout_width="wrap_content"
                android:layout_height="50dp"
                android:layout_marginBottom="20dp"
                android:layout_marginEnd="5dp"
                android:layout_marginRight="5dp"
                android:text="done_btn"
                android:textColor="@color/white" />

            <Button
                android:id="@+id/btn_close_popup"
                android:layout_width="wrap_content"
                android:layout_height="50dp"
                android:layout_marginBottom="20dp"
                android:text="cancel_btn"
                android:textColor="@color/white" />
        </LinearLayout>
    </LinearLayout>
</ScrollView>

对于类中的每个公共方法,是否有一种很好的方法要求(并且希望每次都不要写)internal class Foo { public void Bar() { if (!FooIsEnabled) return; //... } public void Baz() { if (!FooIsEnabled) return; //... } public void Bat() { if (!FooIsEnabled) return; //... } } 部分?

我检查Is there an elegant way to make every method in a class start with a certain block of code?,但这个问题是针对Java的,其答案是使用Java库。

3 个答案:

答案 0 :(得分:7)

您正在寻找的主要是来自Aspect Oriented Programming或AOP域的拦截。

虽然C#不直接支持它,但仍然有坚实的选择:

  1. Postsharp
  2. Unity Interception
  3. Spring.NET
  4. Castle Interceptors
  5. 如果我明天有空,我会为你做一个例子......

答案 1 :(得分:4)

我认为你不能轻易摆脱Bar,Baz,Bat方法中的额外混乱,但你可以通过创建一个方法来执行你传递的动作来使其更易于管理。

internal class Foo
{
    private bool FooIsEnabled;

    public void Bar()
    {
        Execute(() => Debug.WriteLine("Bar"));
    }

    public void Baz()
    {
        Execute(() => Debug.WriteLine("Baz"));
    }

    public void Bat()
    {
        Execute(() => Debug.WriteLine("Bat"));
    }

    public void Execute(Action operation)
    {
        if (operation == null)
            throw new ArgumentNullException("operation");

        if (!FooIsEnabled)
            return;

        operation.Invoke();
    }
}

答案 2 :(得分:2)

不确定

internal interface IFoo {
    void Bar();
    void Baz();
    void Bat();
}

internal class Foo {
    private IFoo FooImplementation = new DisabledFoo() // or new EnabledFoor()

    public bool FooIsEnabled
    {
        get
        {
            return FooImplementation is EnabledFoo;
        }
        set
        {
            FooImplementation = value ? new EnabledFoo() : new DisabledFoo()
        }
    }

    public void Bar() {
        FooImplementation.Bar();
    }
    public void Baz() {
        FooImplementation.Baz();
    }
    public void Bat() {
        FooImplementation.Bat();        
    }
}

internal class EnabledFoo : IFoo {
    public void Bar() {
        //...
    }
    public void Baz() {
        //...
    }
    public void Bat() {
        //...
    }
}

internal class DisabledFoo : IFoo {
    public void Bar() {}
    public void Baz() {}
    public void Bat() {}
}

如果您的目的是模拟单元测试的foo实现,只需删除FooIsEnabled属性并公开FooImplementation。在这种情况下,您还应该删除DisabledFoo,并使用如下的实例进行测试:

var fooImplementationMock = new Mock<IFoo>();
var foo = new Foo { FooImplementation = fooImplementationMock.Object };
foo.Bar();
fooImplementationMock.Verify(f => f.Bar());

鉴于您正在使用moq