I have 2 tables in a database and then using a datamodel in visual studio (datasets), then using 2 classes to store methods and properties of these 2 tables.
I want to store information gathered from a webform into a list but for some reason when trying to add the list to a stateview I get this error:
Type '"".""TableAdapters.""TableAdapter' in Assembly '"", Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
I have already marked the class as serializable but now the tableadapters? Here is my code:
[System.ComponentModel.DataObject]
[Serializable]
public class Example
{
int _example1 = new int();
string _example2;
string _example3;
decimal _example4 = new decimal();
public int example1
{
get { return _example1; }
set { _example1 = value; }
}
public string example2
{
get { return _example2; }
set { _example2 = value; }
}
public string example3
{
get { return _example3; }
set { _example3 = value; }
}
public decimal example4
{
get { return _example4; }
set { _example4 = value; }
}
private tblTestTableAdapter _testAdapter = null;
protected tblTestTableAdapter Adapter
{
get
{
if (_testAdapter == null)
_testAdapter = new tblTestTableAdapter();
return _testAdapter;
}
}
Webform:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
}
else
{
example = (List<Example>)ViewState["Examples"];
}
}
private List<Example> example;
public List<Example> GetExample()
{
return example;
}
protected void btnRow_Click(object sender, EventArgs e)
{
example = new List<Example>();
Example e = new Example();
e.example1 = Convert.ToInt32(txtE1.Text);
c.example2 = txtE2.Text;
c.example3 = txtE3.Text;
c.example4 = Convert.ToDecimal(txtE4.Text);
example.Add(e);
ViewState["Examples"] = example;
btnRow.Enabled = false;
}
What is the problem?
When marking a class as Serializable every class and dependent object class within it that is exposed externally must all be marked as Serializable. That's because whatever process that is going to perform the serialization will attempt to serialize every public element properly.
FYI, tableadapters are not meant to be exposed publicly because they expose functionality rather than properties and fields. Functionality is not transferred across the serial connection. I would recommend you remove the public nature of the adapter in your example.
Edit 2:
After rereading your code and looking for the documentation for the protection levels of serialized properties, I ran into this link that describes the real problem here. You can't serialize a readonly property (I totally forgot about this), and your tableadapter is property is readonly. Provide it with a set, and it should begin functioning.
Edit: Code sample
[Serializable]
public class MySerializableClass
{
public MySerializableClass()
{
}
// This string serializes ok
public string MyStringProperty { get; set; }
// Because this property is public in scope it must be serializable
// because it will be translated at a public scope. This will throw
// an exception
public myNonSerializableClass NotSerializableObject { get; set; }
// Because this property is private in scope, it will not be included
// in any serialization calls, so it will not throw an exception, but
// it will also not be available in whatever remote class calls it.
private myNonSerializableClass SerializableObject { get; set; }
// Because this property object is serializable in code it will be
// ok to make it public because it will natively serialize itself
public MyOtherSerializableClass OtherSerializableObject { get; set; }
}
Related
I'm struggling migrating from protobuf-net v2.4.6 to v3.0.100 (or any 3.0.x) in regards to an existing type hierarchy used as ProtoContracts with one of the subtypes requiring a surrogate due to one of its property being of type object.
With previous configuration in place, I get the following exception thrown on creating the runtime model:
System.InvalidOperationException: 'Types with surrogates cannot be used in inheritance hierarchies'
Hence, my question is how to properly deal with this scenario using protobuf-net 3.0.x?
Here's my (over-)simplified repro of the issue:
class Program
{
static void Main(string[] args)
{
var model = RuntimeTypeModel.Create();
_ = model[typeof(Base)]; // <-- InvalidOperationException thrown here
Base value = new Complex();
var copy = model.DeepClone(value);
}
}
[ProtoContract]
[ProtoInclude(1, typeof(Simple))]
[ProtoInclude(2, typeof(Complex))]
public abstract class Base
{
}
[ProtoContract]
public class Simple : Base
{
}
[ProtoContract(Surrogate = typeof(ComplexSurrogate))]
public class Complex : Base
{
}
[ProtoContract(Name = nameof(Complex))]
public class ComplexSurrogate
{
[ProtoConverter]
public static ComplexSurrogate Convert(Complex source) => new ComplexSurrogate();
[ProtoConverter]
public static Complex Convert(ComplexSurrogate source) => new Complex();
}
As a side note: When compiling protobuf-net from source with the above mentioned exception suppressed, I'm able to defined a surrogate for the Base class which seems to serve as a workaround.
Right now, that scenario isn't supported. While reworking the code for v3, some ambiguous outcomes/intents were found, and it needs work to go in and figure out what the correct outcomes are in each case, design how to achieve that, implement it, and test it. That time has not yet been found, so right now it is safer to prevent a configuration that could lead to big problems downstream, than to just shrug and assume that whatever happens is correct. It is on my list of things to do, but: ultimately this is a project that comes entirely out of my own spare time - it isn't sponsored or part of my paid work, so: it'll get there when it gets there.
I encountered the same error in protobuf v3, and I solved that with custom serializer.
My base class is
[ProtoContract]
[ProtoInclude(500, typeof(XXXRequest))]
[ProtoInclude(501, typeof(XXXResponse))]
// ...
public class MessageBase
{
[ProtoMember(1)]
long ID { get; internal set; }
[ProtoMember(3)]
int ExecutionMilliseconds { get; set; }
}
Its equivalent proto is
message Message {
int64 ID = 1;
int32 ExecutionMilliseconds = 3;
oneof body {
PredictBonusRequest XXXRequest = 500;
PredictBonusResponse XXXResponse = 501;
// ...
}
}
I want to replace some types (e.g. XXXResponse) to use the contract-first class instead. This would allow us to migrate from code-first to contract-first smoothly.
For sub-types should be surrogated, we create custom serializer as below.
using ProtoBuf;
using ProtoBuf.Serializers;
using UnderlyingMessage = GeneratedProto.Contract.Message;
using UnderlyingResponse = GeneratedProto.Contract.XXXResponse;
[DataContract]
[Serializable]
[ProtoContract(Serializer = typeof(XXXResponseSerializer))]
public class XXXResponse : MessageBase
{
class XXXResponseSerializer : ISerializer<XXXResponse>
{
public SerializerFeatures Features => SerializerFeatures.CategoryMessage | SerializerFeatures.WireTypeString;
public XXXResponse Read(ref ProtoReader.State state, XXXResponse value)
{
ISerializer<UnderlyingMessage> serializer = state.GetSerializer<UnderlyingMessage>();
return serializer.Read(ref state, value);
}
public void Write(ref ProtoWriter.State state, XXXResponse value)
{
ISerializer<UnderlyingMessage> serializer = state.GetSerializer<UnderlyingMessage>();
serializer.Write(ref state, value);
}
}
private readonly UnderlyingResponse _resp;
public XXXResponse() : this(new UnderlyingResponse() { })
{
}
private XXXResponse(UnderlyingResponse msg)
{
_resp = msg;
}
public static implicit operator XXXResponse(UnderlyingMessage value)
{
if( value != null)
{
return new XXXResponse(value.XXXResponse)
{
ID = value.ID,
ExecutionMilliseconds = value.ExecutionMilliseconds,
};
}
return null;
}
public static implicit operator UnderlyingMessage(XXXResponse value)
{
if(value != null)
{
return new UnderlyingMessage()
{
ID = value.ID,
ExecutionMilliseconds = value.ExecutionMilliseconds,
XXXResponse = value._resp,
};
}
return null;
}
public Transaction[] Transactions
{
get { return _resp.Transactions?.Select(t => (Transaction)t)?.ToArray(); }
set { _resp.Transactions = value?.Select(t => (BE.Data.Contract.Transaction)t)?.ToList(); }
}
public long DomainID { get { return _resp.DomainID; } set { _resp.DomainID = value; } }
public string UniversalID { get { return _resp.UniversalID; } set { _resp.UniversalID = value; } }
public string ExtraData { get { return _resp.ExtraData; } set { _resp.ExtraData = value; } }
// other proxied fields ...
}
The key is, when ISerializer.Read or ISerializer.Write is fired, the wire-format is from the scope of the entrie message, including all fields of base class, and current sub-type is in a field whose number is identified by ProtoInclude.
In our case this works. For other sub-types which we don't want surrogate at this moment, it still works as it did.
I have 2 classes:
public class Access
{
public class Job
{
public int Id { get; set; }
protected string JobName { get; set; }
}
}
Class2.cs
public class Full: Access.Job
{
}
Full ful = new Full();
Why I'm not able to access the ful.JobName member?
Because You are trying to access protected method from outside the class. Only public methods are available. You can access the property/variably/method that is protected, only in the inherited class, but not from outer code:
public class Full: Access.Job
{
public void mVoid()
{
Console.WriteLine(this.JobName);
}
protected void mProtVoid()
{
Console.WriteLine(this.JobName);
}
private void mPrivateVoid()
{
Console.WriteLine("Hey");
}
}
Full myFull = new Full();
myFull.mVoid(); //will work
myFull.mProtVoid(); //Will not work
myFull.mPrivateVoid(); //Will not work
If You need to get to the protected property, there are 2 ways (3 actually, but Reflection is the dirty way and should be avoided):
1. Make it public
If it will be set to public, it will be stil inherit and You can directly access it:
Full nFull = new Full();
Console.Write(nFull.JobName);
2. Make a "wrapper"/"facade"
Create new property or method, that will just access the hidden property and return it in expected format.
public class Full: Access.Job
{
public string WrappedJobName { get { return this.JobName; } }
public string WrappedJobName => this.JobName; //C# 6.0 syntax
}
Full mFull = new Full();
Console.WriteLine(mFull.WrappedJobName);
I've I really weird problem with my WPF / C# application. I've got a property which returns another property. Now I make a variable and set it to one of these properties. If I now change the value by binding, the variable is also changed.
To simplify it, here's the code:
Here's the first property:
public MainDataObject CmObj_Temp { get; set; }
Which is used here:
public MainDataObject CmObj_MainData {
get {
return TemporaryDataStore.CmObj_Temp;
}
set {
TemporaryDataStore.CmObj_Temp = value;
this.RaisePropertyChanged(() => this.CmObj_MainData);
}
}
From which I set a variable here:
CmObj_Backup = TemporaryDataStore.CmObj_Temp;
or also like this (makes no different):
CmObj_Backup = ((VM)this.DataContext).CmObj_MainData;
And also use for binding here:
<TextBox Text="{Binding CmObj_MainData.Str_Internnr, Mode=TwoWay}"/>
Now if I change the text of the Textbox it also changes it here:
CmObj_Backup.Str_Internnr);
Can someone tell my why?
How can I change that?
Thx
This is an smaller form of my code:
public class DataObject
{
public string Str_Test1 {get; set;}
public string Str_Test2 {get; set;}
// --> Much more properties
}
public static class TempData
{
public static DataObject DObj1 {get;set;}
}
public class ViewModel
{
public DataObject DObj2 {
get {
return TempData.DObj1;
}
set {
TempData.DataObjet.DObj1 = value;
this.RaisePropertyChanged(() => this.DObj2);
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
var VM = new ViewModel();
this.DataContext = VM;
}
public void SomeWhereInTheSoftware()
{
((ViewModel)this.DataContext).DObj2.Str_Test1 = "Before";
ObjBackup = ((ViewModel)this.DataContext).DObj2;
((ViewModel)this.DataContext).DObj2.Str_Test1 = "After";
// --> Here is ObjBackup.Str_Test1 also "After"!!
}
}
If you would show full code blocks instead of randomly chosen lines of code it would be easier to follow. Your example isnt very clear to me.
However, I think you are having an issue because you think you are have 2 copies of an object when you really have 1. Objects are kept as reference so if you create a MainObject and a CopyObject you cant just set CopyObject equal to MainObject and expect to have a real copy.
Again, I could be way off given I dont understand your question fully but for example:
class A {
public string Message { get; set; }
}
public static void Main()
{
A mainData = new A();
mainData.Message = "Main Data Message";
A backupData = mainData;
backupData.Message = "Backup Data Message";
Console.WriteLine(mainData.Message);
// Prints Backup Data Message
Console.WriteLine(backupData.Message);
// Prints Backup Data Message
}
Edit: cloning as a solution
As Viv mentioned in the comment the solution to your problem would be to clone the object, which creates an actual copy of the object as opposed to a reference to the object.
you would update class A in this way:
class A : ICloneable
{
public string Message { get; set; }
public override object Clone()
{
A clone = new A();
clone.Message = this.Message;
return clone;
}
}
reference to ICloneable is here http://msdn.microsoft.com/en-us/library/system.icloneable.aspx
I've been reviewing the PRISM toolkit and I find many examples where they declare a public property with empty getters/setters yet they can still set the property of the instantiated class. How/why is this possible?
public class ShellPresenter
{
public ShellPresenter(IShellView view)
{
View = view;
}
public IShellView View { get; private set; }
}
//calling code
ShellPresenter sp = new ShellPresenter();
//Why is this allowed?
sp.View = someView;
This is a new feature in C# 3.0.
http://msdn.microsoft.com/en-us/library/bb384054.aspx
In C# 3.0 and later, auto-implemented properties make property-declaration more concise when no additional logic is required in the property accessors.
They're using C# auto properties. It's a convenience whereby the compiler generates the backing field for you. private set means that the property is read-only from outside the class. So, if sp.View = someView; is being used outside of the class then it will result in a compiler error.
Decompiling your ShellPresenter with the Red Gate .NET Reflector
public class ShellPresenter
{
// Fields
[CompilerGenerated]
private IShellView <View>k__BackingField;
// Methods
public ShellPresenter(IShellView view)
{
this.View = view;
}
// Properties
public IShellView View
{
[CompilerGenerated]
get
{
return this.<View>k__BackingField;
}
[CompilerGenerated]
private set
{
this.<View>k__BackingField = value;
}
}
}
What you posted is not allowed unless the object is being set within the class itself. Here's a code sample of what is and is not allowed.
public interface IShellView
{
}
public class View:IShellView
{
}
//public class SomeOtherClass
//{
// static void Main()
// {
// IShellView someView = new View();
// //calling code
// ShellPresenter sp = new ShellPresenter();
// //Why is this allowed?
// sp.View = someView;//setting a private set outside the ShellPresenter class is NOT allowed.
// }
//}
public class ShellPresenter
{
public ShellPresenter()
{
}
public ShellPresenter(IShellView view)
{
View = view;
}
static void Main()
{
IShellView someView = new View();
//calling code
ShellPresenter sp = new ShellPresenter();
//Why is this allowed?
sp.View = someView;//because now its within the class
}
public IShellView View { get; private set; }
}
C# compiler generates backend field for you. This syntax was introduced for anonymous types support (like new { A = 1, B = "foo" } )
Typically, if I want to pass an object to an instance of something I would do it like so...
Listing 1
File 1:
public class SomeClass
{
// Some Properties
public SomeClass()
{
public int ID
{
get { return mID; }
set { mID = value; }
}
public string Name
{
set { mName = value; }
get { return mName; }
}
}
}
public class SomeOtherClass
{
// Method 1
private void Method1(int one, int two)
{
SomeClass USER; // Create an instance
Squid RsP = new Squid();
RsP.sqdReadUserConf(USER); // Able to pass 'USER' to class method in different file.
}
}
Similar approach to listing 1 but I was unable to get it to work. What am I doing wrong here?
Listing 2 (this does not work, why?)
File 1:
private void SomeClass1
{
[snip]
TCOpt_fM.AutoUpdate = optAutoUpdate.Checked;
TCOpt_fM.WhiteList = optWhiteList.Checked;
TCOpt_fM.BlackList = optBlackList.Checked;
[snip]
private TCOpt TCOpt_fM;
TCOpt_fM.SaveOptions(TCOpt_fM);
}
File 2:
public class TCOpt:
{
public TCOpt OPTIONS;
[snip]
private bool mAutoUpdate = true;
private bool mWhiteList = true;
private bool mBlackList = true;
[snip]
public bool AutoUpdate
{
get { return mAutoUpdate; }
set { mAutoUpdate = value; }
}
public bool WhiteList
{
get { return mWhiteList; }
set { mWhiteList = value; }
}
public bool BlackList
{
get { return mBlackList; }
set { mBlackList = value; }
}
[snip]
public bool SaveOptions(TCOpt OPTIONS)
{
[snip]
Some things being written out to a file here
[snip]
Squid soSwGP = new Squid();
soSgP.sqdWriteGlobalConf(OPTIONS);
}
}
File 3:
public class SomeClass2
{
public bool sqdWriteGlobalConf(TCOpt OPTIONS)
{
Console.WriteLine(OPTIONS.WhiteSites); // Nothing prints here
Console.WriteLine(OPTIONS.BlackSites); // Or here
}
}
In this example, I was not able to use approach in Listing 1. Probably because Listing 1 passes an object between classes. Whereas, below, things are defined in a single class. I had to use some extra steps (trial & error) to get things to work. I am not sure what I did here or what its called. Is it good programming practice? Or is there is an easier way to do this (like in Listing 1).
Listing 3 (this works)
File 1:
private void SomeClass1
{
private TCOpt TCOpt_fM;
[snip]
TCOpt_fM.AutoUpdate = optAutoUpdate.Checked;
TCOpt_fM.WhiteList = optWhiteList.Checked;
TCOpt_fM.BlackList = optBlackList.Checked;
[snip]
TCOpt_fM.SaveOptions(TCOpt_fM);
}
File 2:
public class TCOpt:
{
public TCOpt OPTIONS;
[snip]
private bool mAutoUpdate = true;
private bool mWhiteList = true;
private bool mBlackList = true;
public bool AutoUpdate
{
get { return mAutoUpdate; }
set { mAutoUpdate = value; }
}
public bool WhiteList
{
get { return mWhiteList; }
set { mWhiteList = value; }
}
public bool BlackList
{
get { return mBlackList; }
set { mBlackList = value; }
}
[snip]
public bool SaveOptions(TCOpt OPTIONS)
{
[snip]
Some things being written out to a file here
[snip]
Squid soSwGP = new Squid();
soSwGP.OPTIONS = OPTIONS;
}
}
File 3:
[snip]
private TCOptions TCOpt_TCS;
public TCOpt OPTIONS
{
get { return TCOpt_TCS; }
set
{
TCOpt_TCS = value;
sqdWriteGlobalConf();
}
[snip]
public class SomeClass2
{
public bool sqdWriteGlobalConf()
{
Console.WriteLine(OPTIONS.WhiteSites);
Console.WriteLine(OPTIONS.BlackSites);
}
}
Thanks in advance,
XO
At first it seems that you have a completely false picture on how OOP works (or hopefully just the wrong words).
You don't pass object between files. You pass them between classes. Normally you would put one class into one file and in that case your description would be right. But nevertheless you can put multiple classes into one file and you can also spawn one class over multiple files (by using the partial keyword).
So to be completely correct, you also don't pass classes. You pass instances of classes. And the problem in your example is that you declare an object of a specific class, but you don't instantiate it:
private void Method1(int one, int two)
{
SomeClass USER; // This doesn't create an instance!
USER = new SomeClass(); //This creates an instance.
//SomeClass USER = new SomeClass(); //Can also be written as one-liner.
Squid RsP = new Squid();
RsP.sqdReadUserConf(USER); // Able to pass 'USER' to class method in different file.
}
Update
After reading your comment i looked into your second and third example. Maybe it is just a typo again in Listing 2 File 1, but cause you changed it in Listing 3 File 1 i think there must somewhere your problem:
private void SomeClass1
{
[snip]
TCOpt_fM.AutoUpdate = optAutoUpdate.Checked;
TCOpt_fM.WhiteList = optWhiteList.Checked;
TCOpt_fM.BlackList = optBlackList.Checked;
[snip]
//It is impossible to declare here a variable name that is already used
//above.
//But it looks like you just declared here a variable (without instantiation)
//and trying to use it as parameter for the SaveOptions() function.
private TCOpt TCOpt_fM;
TCOpt_fM.SaveOptions(TCOpt_fM);
}
Normally this will lead to a couple of error messages.
declaring a variable name that is already used in the same scope
trying to pass an object that is not initialized
(If you like to pass a not initialized object you have to initialize it with null or use the out keyword