【问题标题】:Pass "this" object by reference in C# [duplicate]在C#中通过引用传递“this”对象[重复]
【发布时间】:2014-04-24 05:40:03
【问题描述】:

我需要在 C# 中通过引用传递 this 对象。但如您所知,这是不可能的。 我有一个多层应用程序。简而言之,DAL 从 Web 服务中获取 JSON 格式的数据。 JSON 数据必须在业务层对象中进行转换。因此,我初始化了业务层对象并将其传递给 DAL。 DAL 会将数据转换为对象。我展示了一个代码示例。首先是 DAL:

public Stream  GetSession ( ref BusinessLayer.Session session)
{
    Stream dataStream;
    // Use the ServiceManager to build send the data to the services
    // SOAServiceManager sm = new SOAServiceManager("http://www.Test.da/authentication.json","",DataAccessLayer.HTTPMethod.POST);

    // Add the Values 
    sm.AddCriteriaValue ("name","demo");
    sm.AddCriteriaValue ("password","demo");

    // Now it's show time and the datastream is full
    dataStream = sm.CommitPost ();

    DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(BusinessLayer.Session));

    session = (BusinessLayer.Session)ser.ReadObject(dataStream);

    return dataStream;
}

现在业务层正在使用这个 DAL 类:

namespace BusinessLayer
{
    public class Session
    {
        public bool Success { get; set; }
        public string Name { get; set; } 

        public Session ()
        {
            DataAccessLayer.Session dal_Session = new DataAccessLayer.Session ();
            dal_Session.GetSession ( ref this);
        }
    }
}

所以问题是,不可能发送“this”作为参考。 所以我看到的解决方案是创建一个复制对象并将其发送到 DAL,然后将其值分配给 this 对象。但这不是一个聪明的解决方案。 有没有办法在 C# 中解决这个问题?

【问题讨论】:

  • 我已经阅读了那篇文章,但这不是一个解决方案。如您所见,我已经写过这是可能的,但并不聪明。在这种情况下,“我”会被填满,但“这个”对象不会改变。所以你必须再次将“me”对象的值赋给“this”对象。

标签: c# design-patterns data-access-layer multi-tier


【解决方案1】:

如果您更改应用程序的结构,则绝对不需要这样做。

让 DAL 返回一个Session,而不是分配一个 ref 对象:

public BusinessLayer.Session GetSession ()
{
    //...
    return (BusinessLayer.Session)ser.ReadObject(dataStream);
}

EDIT 无需从构造函数调用该方法。显然,以下仍然不起作用:

public Session ()
{
    this = dal.GetSession();
}

但是,您可以只在调用此构造函数的客户端中进行调用。改变

Session session = new Session();

Session session = dal.GetSession();

或者,如果您想限制客户端和 dal 的耦合,例如可以在 Session 中添加工厂方法:

public class Session
{
    //...

    public static Session GetSession()
    {
        return dal.GetSession();
    }
}

【讨论】:

  • 我以前试过。正如您在代码中看到的,BusinessLayer 会话调用 DAL。因此,如果 DAL 返回一个 BL.Session,我必须将它分配给 this 对象,如下所示: this = dal_Session.GetSession ();这不起作用,因为我无法分配给“this”对象。
  • @Prog 你不应该那样做。查看我的编辑。
  • 这段代码的问题是,你将 DAL 代码插入另一层,并且耦合正在增加。所以如果用户想要在 UI 中声明一个 Session 对象,它必须使用 DAL.GetSession()。但也许工厂模式是一种解决方案。我得看看。
  • @Prog 我明白了,我用静态工厂方法添加了一个潜在的解决方案。
【解决方案2】:

您不应该创建新的Session 对象。而是将DataContractJsonSerializer 替换为Newtonsoft.Json(因为前者不公开此类方法)并使用读取JSON 数据和populates 现有对象的方法:

using (var reader = new Newtonsoft.Json.JsonTextReader(new StreamReader(dataStream)))
{
    var serializer = new Newtonsoft.Json.JsonSerializer();
    serializer.Populate(reader, session);
}

或者不使用构造函数,而是使用静态工厂方法:

public class Session
{
    private Session() { }
    public static Create()
    {
        DataAccessLayer.Session dal_Session = new DataAccessLayer.Session ();
        var session = new Session();
        dal_Session.GetSession (ref session);
        return session;
    }
}

【讨论】:

  • 工厂模式的想法听起来很棒。我现在要测试它。
  • 我尝试了第二种解决方案,它完全有效。非常感谢。
【解决方案3】:

您可以将 this 作为引用,因为对象是引用类型。

【讨论】:

  • -1 试试看。你不能使用ref this,因为它会重新分配this
【解决方案4】:

C# 中的任何非基元始终通过引用传递。考虑这段代码:

public static void Main()
{
    RefType r1 = new RefType();
    RefType r2 = r1;

    r1.Sprop = "hi there";

    Console.WriteLine(r2.Sprop);
}

public class RefType
{
    public string Sprop { get; set; }
}

你认为输出应该是什么?我们从未将r2Sprop 值设置为任何值。但是r2 被设置为等于r1,并且在 VB.Net 和 C# 中,这意味着 r2 和 r1 都具有相同的指针,指向所创建的同一 RefType 对象。

因此,The output is "hi there"

因此,您不需要使用ref 关键字传递this,因为任何可以称为this 的东西都已经是引用类型了。

【讨论】:

  • 我知道。但是如果你在没有 ref 关键字的情况下传递它,你会得到一个错误。因此,您也必须更改函数“GetSession”并删除 ref 关键字。如果您这样做并将“this”对象传递给它,则主要的“this”对象不会改变。我试过了,你也可以测试一下。
  • 该错误仅由GetSession 的参数中的 ref 关键字引起,因此从两个位置删除 ref 就是答案。将ref 传递给引用类型变量并没有像您认为的那样做。这是一个测试,它表明您可以在作为参数传递时从另一个类更改“this”对象上的值:ideone.com/dGc4Zq
  • 你说得对。但这里有点不同。我试过了。这有点奇怪。看:如果我传递“this”对象并像this.name =“newValue”一样更改值,它就可以工作。但是现在看看这个并尝试一下:如果你传递“这个对象并使用 (BusinessLayer.Session)ser.ReadObject(dataStream) 函数,更改的数据不会反射回来。我尝试了其他情况:如果将“newValue”分配给传递的对象值,然后使用此 DataContractJsonSerializer.ReadObject 函数,该值在 DAL 函数中发生变化,但在 BAL 中它具有“newValue”!!
  • 如果您传递对对象的引用 (this) 或对对象的引用的引用 (ref this),那么这个问题几乎没有关系。
  • 但我没有传递对引用的引用,而只是传递“this”对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-28
  • 1970-01-01
  • 2013-08-11
  • 2011-07-06
相关资源
最近更新 更多