2

我有几个共享一些公共属性的用户控件。例子:

private List<MyObject> Sample
        {
            get
            {
                return Session["MyObject"] as List<MyObject>;
            }
            set
            {
                Session["MyObject"] = value;
            }
        }

我想将此分享给我项目中的所有用户控件。(当然,不是解决方案中的其他项目)。我要做的是创建一个单独的类并从该类继承。就像是:

public class SampleBase : Web.UI.UserControl
{
 protected List<MyObject> Sample
            {
                get
                {
                    return Session["MyObject"] as List<MyObject>;
                }
                set
                {
                    Session["MyObject"] = value;
                }
            }
}

然后我的控件可以通过从该类派生来继承这些值:

partial class myControl : SampleBase 

我遇到的一个问题是,如果 control 已经继承了某些东西,我就不能从 base 派生:

partial class myControl : SomethingELSE

否则它工作正常,但我不确定这是否是一个好方法,我正在寻找建议。

4

4 回答 4

10

如果我的理解是正确的,您只想摆脱用户控件的继承层次结构

另一种方法是使用扩展方法

例如:

用于标记您的 USerControls 的界面

public interface IMyUserControlMark { }

扩展

public static class MyUserClassExtensions
{
    public static List<object> GetSampleData(this IMyUserControlMark myUserControl)
    {
        if (HttpContext.Current.Session["MyObject"] == null)
        {
            return Enumerable.Empty<object>().ToList();
        }

        return HttpContext.Current.Session["MyObject"] as List<object>;
    }

    public static void SetSampleData(this IMyUserControlMark myUserControl, List<object> myObject)
    {
        HttpContext.Current.Session["MyObject"] = myObject;
    }
}

用户控制

public partial class Content1 : System.Web.UI.UserControl, IMyUserControlMark
{
     ...
}

public partial class Content2 : System.Web.UI.UserControl, IMyUserControlMark
{
     ....
}

现在您将能够从您的 UserControl 或从后面的 ASPX 代码中调用您的扩展方法,如下所示:

从用户控件

var myObject = this.GetSampleData();
this.SetSampleData(myObject);

来自背后的 ASPX 代码

var myObject = this.uc1.GetSampleData();
this.uc1.SetSampleData(myObject);
于 2012-07-30T20:51:43.973 回答
2

这是一个典型的例子,你需要“优先组合而不是继承”。

您持有对类实例的引用,而不是从类继承。然后,您提供简单的传递代码来访问类的方法/属性。

因此,对于您的示例:

public class SomeBehavior
{
    public List<MyObject> Sample
    {
        get { return Session["MyObject"] as List<MyObject>; }
        set { Session["MyObject"] = value; }
    }
}

public class MyControl : UserControl
{
    private SomeBehavior _someBehavior;

    public MyControl()
    {
        _someBehavior = new SomeBehavior();
    }

    public List<MyObject> Sample
    {
        get { return _someBehavior.Sample; }
        set { _someBehavior.Sample = value; }
    }   
}

另一种选择是允许直接访问行为类:

public class MyControl : UserControl
{
    public SomeBehavior SomeBehavior { get; private set; }

    public MyControl()
    {
        SomeBehavior = new SomeBehavior();
    }
}

这样做的好处是您不必编写传递代码。缺点是它违反了得墨忒耳法则,即你应该“只与你的直系朋友交谈”。如果你这样做,其他使用的类MyControl需要了解SomeBehavior. 遵循得墨忒耳法则可以提高代码的可维护性和适应性,但代价是大量的直通代码。

于 2012-07-25T22:04:12.837 回答
0

除了以前的解决方案,也许是时候应用一些 MVC/MVP 模式了?对于 Web 表单,有一个很棒的框架叫做 WebFormsMVP:link 在库中有一个叫做 Cross Presenter Messaging 的机制,借助它,您可以使用发布/订阅模式在控件之间共享数据。为了更好的解释看这里这里

我建议给图书馆一个机会:)

于 2012-07-30T21:14:46.463 回答
0

在 C# 中,您只能从一个类继承并实现多个接口。

这是允许的:

partial class myControl : SampleBase

partial class myControl : SampleBase, Interface1

partial class myControl : SampleBase, Interface1, Interface2, Interface3

这是不允许的:

partial class myControl : SomethingELSE, SampleBase

如果它满足您的设计,请尝试SomethingELSE继承。SampleBase如果没有,那么我建议将其封装SampleBase为每个需要它的控件的属性,因为它还建议@DanM。

于 2012-08-02T01:32:14.347 回答