在多个用户控件之间共享属性

时间:2012-07-25 22:01:10

标签: c# asp.net

我有几个共享一些常见属性的UserControl。例如:

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 

我遇到的一个问题是,如果控件已经存在继承的东西,我无法从base派生:

partial class myControl : SomethingELSE

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

4 个答案:

答案 0 :(得分:10)

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

另一种方法是使用Extension Methods

例如:

标记您的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代码中调用您的扩展方法,如下所示:

来自UserControl

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

来自后面的ASPX代码

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

答案 1 :(得分: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();
    }
}

这样做的好处是您不必编写传递代码。缺点是它违反了Law of Demeter,它表示你应该“只与你的直接朋友交谈”。如果您这样做,其他使用MyControl的类需要了解SomeBehavior。遵循Demeter法则可以提高代码的可维护性和适应性,但需要花费大量的传递代码。

答案 2 :(得分:0)

除了以前的解决方案,也许是时候应用一些MVC / MVP模式了? 对于Web表单,有一个很棒的框架,名为WebFormsMVP:link 在库中有一种称为Cross Presenter Messaging的机制,您可以使用发布/订阅模式在控件之间共享数据。 有关更好的说明,请查看herehere

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

答案 3 :(得分: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。