无法通过第三方提供的嵌套类型访问外部类型 XXX 的非静态成员 class
Cannot access a non-static member of outer type XXX via nested type with a third-party provided class
一般情况下,SOF 中已解决此问题。但是,我无法(不够称职)将这些建议应用到这个例子中。我收到 "Cannot access a non-static member of outer type 'FixClientTest.Form1' via nested type ... " 错误。在这种情况下,嵌套类型是第 3 方提供的 class 的实例化(在这种情况下,是开源 QuickFix/n 库)。我知道来源并不是真正相关,但我试图避免任何可能让我修改该代码并且不具备解决问题的知识的建议。我的目标只是根据我从该库的回调中获得的信息更新表单控件。 (下面的代码只是一个带有 2 个按钮的简单表单,一个用于设置事件回调,另一个用于停止它们。)我将不胜感激社区可能提出的任何建议。
谢谢。
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using QuickFix;
namespace FixClientTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public class MyQuickFixApp : QuickFix.IApplication
{
public void FromApp(QuickFix.Message msg, SessionID sessionID) { }
public void OnCreate(SessionID sessionID) { }
public void OnLogout(SessionID sessionID)
{
Console.WriteLine("Logged out.");
}
public void OnLogon(SessionID sessionID)
{
Console.WriteLine("Logged In.");
}
public void FromAdmin(QuickFix.Message msg, SessionID sessionID)
{
//logListView.Items.Add(msg.ToString()); <<GENERATES ERROR!
}
public void ToAdmin(QuickFix.Message msg, SessionID sessionID) { }
public void ToApp(QuickFix.Message msg, SessionID sessionID) { }
}
public QuickFix.Transport.SocketInitiator _Initiator = null;
private void connectButton_Click(object sender, EventArgs e)
{
string file = "c:/FIX/tradeclientIB.cfg";
try
{
QuickFix.SessionSettings settings = new QuickFix.SessionSettings(file);
QuickFix.IApplication myApp = new MyQuickFixApp();
QuickFix.IMessageStoreFactory storeFactory = new QuickFix.FileStoreFactory(settings);
QuickFix.ILogFactory logFactory = new QuickFix.ScreenLogFactory(settings);
_Initiator = new QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory);
_Initiator.Start();
}
catch (System.Exception err)
{
MessageBox.Show(err.ToString());
}
}
private void stopButton_Click(object sender, EventArgs e)
{
_Initiator.Stop();
}
}
}
您的 MyQuickFixApp
class 对 Form1
对象一无所知。
首先,我建议将其移出 Form1
class。
然后,我将查看如何以及何时创建 MyQuickFixApp
对象。我不熟悉 QuickFix 库,但快速浏览文档表明在按钮消息处理程序中创建它不是执行此操作的正确方法。 (在 winforms 应用程序中,我想您会在 Program.Main
方法中创建它)。
至于真正的错误,你需要给MyQuickFixApp
对象一个对Form1
对象的引用(可能在构造函数中传递)。
public class MyQuickFixApp : QuickFix.IApplication
{
private readonly Form1 _form1;
public MyQuickFixApp(Form1 form)
{
_form1 = form;
}
public void FromAdmin(QuickFix.Message msg, SessionID sessionID)
{
_form1.logListView.Items.Add(msg.ToString());
}
}
在等待答案的过程中,我又看了一眼link中提供的答案:
Property is inaccessible due to its protection level 这次再仔细看了一遍,发现Steve贴出了我需要的答案,果然是他的答案。我需要使用事件来重构它以捕获表单中的更改并保留封装。它还允许我将更新表单的 class 从表单 class 中移出,但是,它产生了令人担忧的 "cross-thread" 问题。我已经从其他人那里得到了答案(抱歉,没有 link)。我在更新表单的事件中添加了行,将其作为一个新线程分离出来。我以前做过,效果很好。如果有人认为这可能是个问题,请告诉我。如果我浪费了任何人的时间来查看我的问题,我深表歉意,但我想我会分享答案的组合,因为它解决了自学习 c#/forms 以来我遇到的两个最大问题。
有一件事,不要对这个声明感到困惑:private delegate void AddLogItemDelegate(string msg);
它与创建包含 AddLogItem 函数的线程有关,而不与事件的创建有关。
谢谢
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using QuickFix;
namespace FixClientTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public QuickFix.Transport.SocketInitiator _Initiator = null;
private void connectButton_Click(object sender, EventArgs e)
{
string file = "c:/FIX/tradeclientIB.cfg";
try
{
QuickFix.SessionSettings settings = new QuickFix.SessionSettings(file);
QuickFix.IApplication myApp = new MyQuickFixApp();
QuickFix.IMessageStoreFactory storeFactory = new QuickFix.FileStoreFactory(settings);
QuickFix.ILogFactory logFactory = new QuickFix.ScreenLogFactory(settings);
//QuickFix.Transport.SocketInitiator initiator = new QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory);
_Initiator = new QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory);
MyQuickFixApp.UpdateEvent += new MyQuickFixApp.OnUpdateEvent(AddLogItem);
_Initiator.Start();
}
catch (System.Exception err)
{
Console.WriteLine(err.Message);
Console.WriteLine(err.StackTrace);
MessageBox.Show(err.ToString());
}
}
private void stopButton_Click(object sender, EventArgs e)
{
_Initiator.Stop();
}
public string stuff;
private delegate void AddLogItemDelegate(string msg);
public void AddLogItem(string msg)
{
if(this.InvokeRequired)
{
this.Invoke(new AddLogItemDelegate(AddLogItem), new object[] { msg });
return;
}
try
{
logListView.Items.Add(msg);
}
catch(Exception err)
{
MessageBox.Show(err.ToString());
}
}
}
public class MyQuickFixApp : QuickFix.IApplication
{
public delegate void OnUpdateEvent(string msg);
public static event OnUpdateEvent UpdateEvent;
public void FromApp(QuickFix.Message msg, SessionID sessionID) { }
public void OnCreate(SessionID sessionID) { }
public void OnLogout(SessionID sessionID)
{
Console.WriteLine("Logged out.");
}
public void OnLogon(SessionID sessionID)
{
UpdateEvent("STUFF!!");
Console.WriteLine("Logged In.");
}
public void FromAdmin(QuickFix.Message msg, SessionID sessionID)
{
}
public void ToAdmin(QuickFix.Message msg, SessionID sessionID) { }
public void ToApp(QuickFix.Message msg, SessionID sessionID) { }
}
}
一般情况下,SOF 中已解决此问题。但是,我无法(不够称职)将这些建议应用到这个例子中。我收到 "Cannot access a non-static member of outer type 'FixClientTest.Form1' via nested type ... " 错误。在这种情况下,嵌套类型是第 3 方提供的 class 的实例化(在这种情况下,是开源 QuickFix/n 库)。我知道来源并不是真正相关,但我试图避免任何可能让我修改该代码并且不具备解决问题的知识的建议。我的目标只是根据我从该库的回调中获得的信息更新表单控件。 (下面的代码只是一个带有 2 个按钮的简单表单,一个用于设置事件回调,另一个用于停止它们。)我将不胜感激社区可能提出的任何建议。
谢谢。
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using QuickFix;
namespace FixClientTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public class MyQuickFixApp : QuickFix.IApplication
{
public void FromApp(QuickFix.Message msg, SessionID sessionID) { }
public void OnCreate(SessionID sessionID) { }
public void OnLogout(SessionID sessionID)
{
Console.WriteLine("Logged out.");
}
public void OnLogon(SessionID sessionID)
{
Console.WriteLine("Logged In.");
}
public void FromAdmin(QuickFix.Message msg, SessionID sessionID)
{
//logListView.Items.Add(msg.ToString()); <<GENERATES ERROR!
}
public void ToAdmin(QuickFix.Message msg, SessionID sessionID) { }
public void ToApp(QuickFix.Message msg, SessionID sessionID) { }
}
public QuickFix.Transport.SocketInitiator _Initiator = null;
private void connectButton_Click(object sender, EventArgs e)
{
string file = "c:/FIX/tradeclientIB.cfg";
try
{
QuickFix.SessionSettings settings = new QuickFix.SessionSettings(file);
QuickFix.IApplication myApp = new MyQuickFixApp();
QuickFix.IMessageStoreFactory storeFactory = new QuickFix.FileStoreFactory(settings);
QuickFix.ILogFactory logFactory = new QuickFix.ScreenLogFactory(settings);
_Initiator = new QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory);
_Initiator.Start();
}
catch (System.Exception err)
{
MessageBox.Show(err.ToString());
}
}
private void stopButton_Click(object sender, EventArgs e)
{
_Initiator.Stop();
}
}
}
您的 MyQuickFixApp
class 对 Form1
对象一无所知。
首先,我建议将其移出 Form1
class。
然后,我将查看如何以及何时创建 MyQuickFixApp
对象。我不熟悉 QuickFix 库,但快速浏览文档表明在按钮消息处理程序中创建它不是执行此操作的正确方法。 (在 winforms 应用程序中,我想您会在 Program.Main
方法中创建它)。
至于真正的错误,你需要给MyQuickFixApp
对象一个对Form1
对象的引用(可能在构造函数中传递)。
public class MyQuickFixApp : QuickFix.IApplication
{
private readonly Form1 _form1;
public MyQuickFixApp(Form1 form)
{
_form1 = form;
}
public void FromAdmin(QuickFix.Message msg, SessionID sessionID)
{
_form1.logListView.Items.Add(msg.ToString());
}
}
在等待答案的过程中,我又看了一眼link中提供的答案: Property is inaccessible due to its protection level 这次再仔细看了一遍,发现Steve贴出了我需要的答案,果然是他的答案。我需要使用事件来重构它以捕获表单中的更改并保留封装。它还允许我将更新表单的 class 从表单 class 中移出,但是,它产生了令人担忧的 "cross-thread" 问题。我已经从其他人那里得到了答案(抱歉,没有 link)。我在更新表单的事件中添加了行,将其作为一个新线程分离出来。我以前做过,效果很好。如果有人认为这可能是个问题,请告诉我。如果我浪费了任何人的时间来查看我的问题,我深表歉意,但我想我会分享答案的组合,因为它解决了自学习 c#/forms 以来我遇到的两个最大问题。
有一件事,不要对这个声明感到困惑:private delegate void AddLogItemDelegate(string msg);
它与创建包含 AddLogItem 函数的线程有关,而不与事件的创建有关。
谢谢
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using QuickFix;
namespace FixClientTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public QuickFix.Transport.SocketInitiator _Initiator = null;
private void connectButton_Click(object sender, EventArgs e)
{
string file = "c:/FIX/tradeclientIB.cfg";
try
{
QuickFix.SessionSettings settings = new QuickFix.SessionSettings(file);
QuickFix.IApplication myApp = new MyQuickFixApp();
QuickFix.IMessageStoreFactory storeFactory = new QuickFix.FileStoreFactory(settings);
QuickFix.ILogFactory logFactory = new QuickFix.ScreenLogFactory(settings);
//QuickFix.Transport.SocketInitiator initiator = new QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory);
_Initiator = new QuickFix.Transport.SocketInitiator(myApp, storeFactory, settings, logFactory);
MyQuickFixApp.UpdateEvent += new MyQuickFixApp.OnUpdateEvent(AddLogItem);
_Initiator.Start();
}
catch (System.Exception err)
{
Console.WriteLine(err.Message);
Console.WriteLine(err.StackTrace);
MessageBox.Show(err.ToString());
}
}
private void stopButton_Click(object sender, EventArgs e)
{
_Initiator.Stop();
}
public string stuff;
private delegate void AddLogItemDelegate(string msg);
public void AddLogItem(string msg)
{
if(this.InvokeRequired)
{
this.Invoke(new AddLogItemDelegate(AddLogItem), new object[] { msg });
return;
}
try
{
logListView.Items.Add(msg);
}
catch(Exception err)
{
MessageBox.Show(err.ToString());
}
}
}
public class MyQuickFixApp : QuickFix.IApplication
{
public delegate void OnUpdateEvent(string msg);
public static event OnUpdateEvent UpdateEvent;
public void FromApp(QuickFix.Message msg, SessionID sessionID) { }
public void OnCreate(SessionID sessionID) { }
public void OnLogout(SessionID sessionID)
{
Console.WriteLine("Logged out.");
}
public void OnLogon(SessionID sessionID)
{
UpdateEvent("STUFF!!");
Console.WriteLine("Logged In.");
}
public void FromAdmin(QuickFix.Message msg, SessionID sessionID)
{
}
public void ToAdmin(QuickFix.Message msg, SessionID sessionID) { }
public void ToApp(QuickFix.Message msg, SessionID sessionID) { }
}
}