I'm getting the follow message when I try to call a routine which creates an
instance of my class TG.ADO.DataConnector.ADOConnectorColumn.
The calling code is
//
try {Inquire();}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
catch {}
The runtime error is
Derived method GetObjectData in type TG.ADO.DataConnector.ADOConnectorColumn
from assembly TG.ADO, Version=4.3.13.1, Culture=neutral,
PublicKeyToken=d6af0e7fcb70d177 can not reduce access.
The Inquire() method is
public override bool Inquire()
{
bool bNeedToOpen = (_adoConn == null);
ADODB.Recordset rs = null;
try
{
// OleDbConnection
if (bNeedToOpen)
{
// // Skip if couldn't open the file.
_adoConn = ADOHelper.OpenConnection(ConnectionString,
ADODB.ConnectOptionEnum.adConnectUnspecified);
if (_adoConn == null)
return false;
}
// Get a recordset from the table
Object RecordsAffected = null;
string cmdStr = String.Format(@"select * from {0}", _Name);
rs = _adoConn.Execute(cmdStr, out RecordsAffected, (int)
ADODB.CommandTypeEnum.adCmdText);
// Clear the schema information
Schema.Clear();
// Loop over the fields and update the summary information.
StringCollection fields = new StringCollection();
foreach (ADODB.Field field in rs.Fields)
{
fields.Add(field.Name);
// Add the field to the schema
TG.Data.DataColumn dc = new ADOConnectorColumn(field);
Schema.Columns.Add(dc);
}
_SummaryInfo["Columns"] = fields;
}
catch {}
finally
{
if (rs != null)
rs.Close();
// Close if needed
if (bNeedToOpen)
{
_adoConn.Close();
_adoConn = null;
}
}
return true;
}
but the first line of the method isn't being reached (i.e. the runtime is
throwing the exception before invoking the method).
The ADOConnectorColumn class is a C# class defined as
using System;
using System.Collections;
using System.ComponentModel;
using System.Runtime.Serialization;
using TG.Core;
using TG.Data;
namespace TG.ADO.DataConnector
{
/// <summary>
/// Summary description for ADOConnectorColumn.
/// </summary>
[Serializable]
public class ADOConnectorColumn : TG.Data.DataColumn, ISerializable
{
protected ADOConnectorColumn() : this(string.Empty) {}
public ADOConnectorColumn(string fieldname) : base(fieldname)
{
}
public ADOConnectorColumn(ADODB.Field field) : this(field.Name)
{
}
// -----------------------------------------
#region // ISerializable
protected ADOConnectorColumn(SerializationInfo info, StreamingContext
context) {}
protected override void GetObjectData(SerializationInfo info,
StreamingContext context) {}
#endregion
}
}
TG.Data.DataColumn is a C++ managed abstract class. A derived class in the same
assembly as TG.Data.DataColumn works fine.
All the references are correct as far as I can see, and the entire project
builds with 0 errors and only 1 warning in the c++ class (LINK : warning
LNK4243: DLL containing objects compiled with /clr is not linked with /NOENTRY;
image may not run correctly). VS.net 2003/DX9 summer 2004 release/XPSP2.
Googling was no help.
Any suggestions?
TIA
Steve.
Steven Ireland - 28 Aug 2004 11:11 GMT
And as usually happens when I post a question to a newsgroup, I find a
workaround almost straight away :)
By changing the definition of
protected override void GetObjectData(SerializationInfo info, StreamingContext
context) {}
to
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext
context) {}
the code now works.
I'd tried various combinations of the ISerializable interface and the
[Serializable] attribute without success.
Does anybody know what the "can not reduce access" error means?
Steve.
>I'm getting the follow message when I try to call a routine which creates an
>instance of my class TG.ADO.DataConnector.ADOConnectorColumn.
[quoted text clipped - 130 lines]
>TIA
>Steve.
Steven Ireland - 29 Aug 2004 06:23 GMT
FYI, I believe the problem was the base class definition in the c++ project
// --------------------------------------------------
// ISerializable
protected:
MyDataColumn(SerializationInfo* info, StreamingContext context);
virtual void GetObjectData(SerializationInfo* info, StreamingContext context);
This made GetObjectData protected. Derived classes in the same assembly worked fine.
However from another assembly, it looks like reflection is used to find a public GetObjectData
method in a derived class. As a public member couldn't be found, the runtime was unable to call
any method which declared an instance of the derived class.
By adding a public: access specifier, the problem went away ie
// --------------------------------------------------
// ISerializable
protected:
MyDataColumn(SerializationInfo* info, StreamingContext context);
public:
virtual void GetObjectData(SerializationInfo* info, StreamingContext context);
which is the correct ISerializable member definition.
I hope that helps someone else.
Steve.