Derived method GetObjectData .... can not reduce access. (runtime error)

  • Thread starter Thread starter Steven Ireland
  • Start date Start date
S

Steven Ireland

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.
 
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.





Steven Ireland said:
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.
 
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.
 
Back
Top