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
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'm trying to implement a PATCH on Web API for an object that will be stored in a DB. The input object from the controller has all of the properties that can be modified but we allow the client to choose which fields to send back. We only want to update the MongoDB representation if some of the fields have changed or been set. We started using a Dirty object pattern (not sure this is a pattern) whereby when you set a property you also record that it is dirty. for instance
public class Example
{
private string _title;
public string Title
{
get { return _title; }
set
{
_title = value;
TitleWasSet = true;
}
}
public bool TitleWasSet {get;set;}
}
This could work but is kind of tedious and I feel it exposes lots of logic that could be contained.
So a solution I came up with was to store the update Actions in the inbound object then reapply them to the Mongo Object in a Try Update fashion.
like this:
public class Data
{
public string Header { get; set; }
public int Rating { get; set; }
}
public class EditDataRequest
{
private readonly List<Action<Data>> _updates;
public EditDataRequest()
{
_updates = new List<Action<Data>>();
}
public string Header
{
set
{
_updates.Add(data => {data.Header = value;});
}
}
public int Rating
{
set
{
_updates.Add(data => {data.Rating = value;});
}
}
public bool TryUpdateFromMe(Data original)
{
if (_updates.Count == 0)
return false;
foreach (var update in _updates)
{
update.Invoke(original);
}
return true;
}
}
Now this would work great but it doesn't take account of the values being the same. So i then looked at changing the list of actions to a list of functions that would return a bool if there was a difference in the value.
private readonly List<Func<Data, bool>> _updates;
And then the properties would look like this:
public int Rating
{
set
{
_updates.Add(data => {
if (data.Rating != value)
{
data.Rating = value;
return true;
}
return false;
});
}
}
And the try update method...
public bool TryUpdateFromMe(Data original)
{
if (_updates.Count == 0)
return false;
bool changesRequired = false;
foreach (var update in _updates)
{
changesRequired |= update.Invoke(original);
}
return changesRequired;
}
As you can see that property set implementation is rather clunky and would make the code nasty to read.
I'd like a way of extracting the check this property value then update it to another method that I can reuse in each property - I assume this is possibly somehow but it might not be.
Of course, if you have better suggestions for how to handle the PATCH situation then I'd be happy to hear them as well.
Thanks for reading this far.
I have an object that only initializes itself with barebones data when constructed (fast), and loads itself for real (slow) when first accessed. The idea is that I'm creating a lot of these barebones objects at startup and hash them into a map, then fully load each object whenever it is individually accessed for the first time. The problem is that I cannot guarantee how clients will interact with this object, there are multiple public methods that might be invoked.
Is there a good pattern to support this kind of situation? The obvious (and my current) solution is to track state with an internal bool, check against that bool in every function that might be invoked, and load that way. But that requires code duplication of that behavior across all public functions, and is vulnerable to errors.
I can imagine a single point-of-entry method that then dishes out behaviors based on a client request type etc., but before I go consider going down that road I want to see if there's a commonly accepted approach/pattern that I might not be aware of. I'm doing this in C#, but any insight is appreciated.
If I understood what you want to achieve, you are looking for the Proxy Design Pattern, more specifically, a virtual Proxy.
Refer to http://www.dofactory.com/net/proxy-design-pattern
A small example would be something like:
public abstract class IObjectProvider
{
public abstract IObjectProvider Object{get;}
public abstract void doStuff();
}
public class RealObject : IObjectProvider
{
public RealObject()
{
//Do very complicated and time taking stuff;
}
public override IObjectProvider Object
{
get { return this; }
}
public override void doStuff()
{
//do this stuff that these objects normally do
}
}
public class ObjectProxy : IObjectProvider
{
private IObjectProvider objectInstance = null;
public override IObjectProvider Object
{
get
{
if (objectInstance == null)
objectInstance = new RealObject();
return objectInstance;
}
}
public override void doStuff()
{
if(objectInstance!=null)
objectInstance.doStuff();
}
}
public class SkeletonClass
{
public IObjectProvider Proxy1 = new ObjectProxy();
public IObjectProvider Proxy2 = new ObjectProxy();
}
static void Main(String[] args)
{
//Objects Not Loaded
SkeletonClass skeleton = new SkeletonClass();
//Proxy1 loads object1 on demand
skeleton.Proxy1.Object.doStuff();
//Proxy2 not loaded object2 until someone needs it
}
Here's an example of dynamic proxy approach.
using System;
using System.Diagnostics;
using Castle.DynamicProxy; //Remember to include a reference, too. It's nugettable package is Castle.Core
namespace ConsoleApp
{
public class ActualClass
{
//Have static instances of two below for performance
private static ProxyGenerator pg = new ProxyGenerator();
private static ActualClassInterceptor interceptor = new ActualClassInterceptor();
//This is how we get ActualClass items that are wrapped in the Dynamic Proxy
public static ActualClass getActualClassInstance()
{
ActualClass instance = new ActualClass();
return pg.CreateClassProxyWithTarget<ActualClass>(instance, interceptor);
}
//Tracking whether init has been called
private bool initialized = false;
//Will be used as evidence of true initialization, i.e. no longer null
private int? someValue = null;
public void Initialize()
{
if (!initialized)
{
//do some initialization here.
someValue = -1; //Will only get set to non-null if we've run this line.
initialized = true;
}
}
//Any methods you want to intercept need to be virtual!
public virtual int replaceValue(int value)
{
//below will blow up, if someValue has not been set to -1 via Initialize();
int oldValue = someValue.Value;
someValue = value;
return oldValue;
}
//block off constructor from public to enforce use of getActualClassInstance
protected ActualClass() { }
}
public class ActualClassInterceptor : ActualClass, IInterceptor
{
public void Intercept(IInvocation invocation)
{
//Call initialize before proceeding to call the intercepted method
//Worth noting that this is the only place we actually call Initialize()
((ActualClass)invocation.InvocationTarget).Initialize();
invocation.Proceed();
}
}
class Program
{
static void Main(string[] args)
{
ActualClass instance1 = ActualClass.getActualClassInstance();
ActualClass instance2 = ActualClass.getActualClassInstance();
int x1 = instance1.replaceValue(41);
int x2 = instance2.replaceValue(42);
int y1 = instance1.replaceValue(82);
Debug.Assert(y1 == 41);
int y2 = instance2.replaceValue(84);
Debug.Assert(y2 == 42);
var read = Console.ReadKey();
}
}
}
EDIT: Question Reconstructed.
OK, I have revisited my get and set methods, but I am still very unclear on how it all works.
What I want to achieve is the Model is populated by the Controller, from the values that it takes form the form. This is then sent to the Db_Facade, which compares the uName and uPwd, and if they are equal returns the ACCESS, which will be set for the entire scope of the program.
I don't know if the get and set declarations are done correctly, or if they can be bunched together (If this is possible it would be great because I will be using this for much larger collections of data), and I'm pretty sure I'm implementing them wrong as well.
If you can help, my knowledge of Accessors is incredibly limited.
Here is my Compare Login method in my Controller:
public static void Compare_Login(User_Login_View Login_View)
{
User_Model getACCESS = new User_Model(); // Creates a new oject of User_Model
getACCESS.Name = Login_View.txtUsername.Text; //Populates the Model from the Login View
getACCESS.Pwd = Login_View.txtPassword.Text;
if (getACCESS.ACCESSLEVEL > 0)
{
Login_View.Close();
}
else
{
Login_View.lblError.Visible = true;
}
Login_View.Menu.SetMenuView();
}
Here is my Model:
public class User_Model
{
public string Name
{
get
{
return Db_Facade.uName;
}
set
{
Db_Facade.uName = value;
}
}
public string Pwd
{
get
{
return Db_Facade.uPwd;
}
set
{
Db_Facade.uPwd = value;
}
}
public int ACCESSLEVEL
{
get
{
return Db_Facade.ACCESS;
}
set
{
Db_Facade.ACCESS = value;
}
}
}
Here is the dummy database comparison:
class Db_Facade
{
public static string uName;
public static string uPwd;
public static string cPwd;
public static int ACCESS;
public static void getLoginACCESS()
{
uName = "paul";
uPwd = "pwd";
ACCESS = 1;
/* I get a "getACCESS does not exist" error here
if (uName == getACCESS.Name && uPwd == getACCESS.Pwd)
{
getACCESS.ACCESSLEVEL = ACCESS;
}
else
{
getACCESS.ACCESSLEVEL = 0;
}
*/
}
}
I don't know if it's needed, but here is my View
public partial class User_Login_View : Form
{
public Menu_View Menu { get; set; }
public User_Login_View()
{
InitializeComponent();
}
private void btnLogin_Click(object sender, EventArgs e)
{
User_Controller.Compare_Login(this);
}
}
2 Questions / Hints
1.) Where do you call your getLoginACCESS() ?
2.) Why do you think Db_Facade is able to access getACCESSfrom your class User_Controller?
a solution would be to modyfie your getLoginACCESS() to getLoginACCESS(User_Model getACCESS) and than call it in your Compare_Login(User_Login_View Login_View) befor your if like Db_Facade.etLoginACCESS(getACCESS);
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; }
}