How do I constrain property setter on Linq-To-Sql class
I have a custom field that needs validation and the designer class can be over written.
I have overrider setter methods which would work but how to I restrict setting on the Linq-To-Sql class?
public partial class Frequency : INotifyPropertyChanging, INotifyPropertyChanged
{
public void SetStartTime(TimeSpan startTime)
{
if(startTime.Days > 0){throw new Exception("No day value is valid for start time value";}
this._StartTime = string.Format("{0}:hh\\:mm\\:ss", startTime);
}
public TimeSpan GetStartTime()
{
IEnumerable<int> startTime = this._StartTime.Split(':').Cast<int>();
return new TimeSpan(startTime.ElementAt<int>(0), startTime.ElementAt<int>(1), startTime.ElementAt<int>(2));
}
}
LINQ 2 SQL has everything you need to overcome this problem if you use the LINQ to SQL Classes designer.
Let's say your table has a column "Number" of type Int32.
The designer will create:
Field -> _Number
Property -> Number
Method -> OnNumberChanging(int value)
Method -> OnNumberChanged()
The last 2 methods are partial. This means you don't have to touch the designer generated files in case you refresh your classes from the database.
By creating the following in another file:
public partial class MyLinqToSqlClass
{
partial void OnNumberChanging(int value)
{
//your code here
//throw exception if necessary when validating
}
}
you get what you need.
This piece of code gets called inside the set method of the Number property right before the value of the field gets changed.
This way you don't worry about using the set method of the property.
Hope this helps.
Related
I create a user control like below:
public partial class TestControl : UserControl
{
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public State MyState
{
get { return new State(this); }
}
internal int[] _internalStates;
[TypeConverter(typeof(ExpandableObjectConverter))]
public struct State
{
private TestControl _myControl;
public State(TestControl _) { _myControl = _; }
public int Data
{
get { return _myControl._internalStates[0]; }
set { _myControl._internalStates[0] = value; }
}
}
}
Then I can drag the control from toolbox and modify the Data value in the designer.
The problem is the designer will generate this code in InitializeComponent method:
this.testControl1.MyState.Data = 0;
But this line will throw an error:
Cannot modify the return value of 'TestControl.MyState' because it is not a variable
I understand why the statement is error, the question is how can I control the code generation to correct the error, for example to generate code like this?
var myState = this.testControl1.MyState;
myState.Data = 0;
More information
State struct is just a bridge to modify the internal property in TestControl
So I want to keep State as a struct to avoid GC overhead.
The reason for not define property in TestControl class is there are multiple states in the class, and a state will contain multiple properties, so I need to wrap the modification methods rather than define a lot of properties in the TestControl class.
Why a compile time error for Control.StructProperty.Member = Value;?
Consider the following statement
this.Control.StructProperty.Value = 0;
StructProperty is a property, so first its getter will execute and since it's a structure and is a value type, it will return a copy of the struct and setting a property for that copy is not useful/working. The knows about the situation well and instead of compiling a confusing non-working code, it generates Compiler Error CS1612:
Cannot modify the return value of 'expression' because it is not a
variable
How can I generate a working code for a Struct property?
You probably have noticed that you cannot assign this.Size.Width = 100 with the same reason. And the way that form generates the code for Size property is:
this.Size = new Size(100,100);
You also can generate code for the property the same way, by implementing a type descriptor by deriving from TypeConverter returning an InstanceDescriptor in its ConvertTo method to generate the code for your structure property using a parametric constructor which you should have for the struct.
In general, I suggest using classes rather that structures for such property.
I want to provide predefined filters for displaying search results. The filter is more or less stored as an expression tree and can be constructed using a rule editor.
I want to provide the user with an editor, select a property, select the operator and allow the user to provide or select a value to compare with.
[dropdown with properties = PriorityId] [dropdown with operators = Equals] [dropdown with values = IList()]
The challenge is that the user needs to get a list of values to select from and I am figuring out how to
I have thought about the following approach, and I would like to get your input on this.
Decorate the property with an attribute
The attribute maps a class responsible for returning possible values
The mapping class implements an interface
When selecting the property from the rule editor I can execute an ajax call to a supporting controller to get the values back. In this controller I can invoke the mapping class via reflection to return the values.
namespace Tickets.Data.Model
{
public class Ticket : BaseModel
{
[RuleEditorCollectionMapping(typeof(GetPriorities))]
public string PriorityId { get; set; }
}
}
public class RuleEditorCollectionMappingAttribute : Attribute
{
private Type classType;
public RuleEditorCollectionMappingAttribute(Type classType)
{
this.classType = classType;
}
}
public interface IRuleEditorCollectionMapping{}
public class GetPriorities : IRuleEditorCollectionMapping
{
public static IList<TicketPriority> GetValues()
{
// query logic to build a list with values to be used in the rules editor when selecting PriorityId
return new List<TicketPriority>();
}
}
Questions:
Is my approach a viable one? More or less a sanity check so I don't take the wrong turn.
If not, do you have any other suggestions or guidance from experience to approach this situation?
So, my question is about the exact methodology behind windows form data binding.
I wrote a simple code, where i created a View, an IViewModel interface and a ViewModel.
interface IVM
{
}
and
public class Vm : IVM
{
int number;
public int Number
{
get
{
return this.number;
}
set
{
this.number = value;
}
}
}
the form looks like:
public partial class Form1 : Form
{
private IVM vm;
public Form1()
{
InitializeComponent();
this.vm = new Vm();
this.iVMBindingSource.DataSource = this.vm;
}
}
and the related designer part is:
this.textBox1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.iVMBindingSource, "Number", true));
...
this.iVMBindingSource.DataSource = typeof(WindowsFormsApplication1.IVM);
You can clearly see that IViewModel interface does not publish a Number property, but the concrete ViewModel class has a Number property.
Although in design time i can't use the designer to bind the property (since IVM has no Number prop), i can manually write "iVMBindingSource - Number" into the textbox's Test property, to bind it.
My question is, how does binding work EXACTLY? Why don't I receive a runtime error, while trying to access IVM's not existing Number property?
(I tested and it actually changes the VM's Number prop properly)
Does it use some kind of reflection? How does this "magic" binding string works?
Thanks for your answers!
Jup it's done by reflection. I just checked the code and the binding is done by the Binding class. There is a method called CheckBindings which ensures the property you want to bind on is available. It basically works like this:
if (this.control != null && this.propertyName.Length > 0)
{
// ...certain checks...
// get PropertyDescriptorCollection (all properties)
for (int index = 0; index < descriptorCollection.Count; ++index)
{
// select the descriptor for the requested property
}
// validation
// setup binding
}
As Ike mentioned, you can find the source code here:
http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Binding.cs,3fb776d540d0e8ac
MSDN Reference: https://msdn.microsoft.com/en-us/library/system.windows.forms.binding(v=vs.110).aspx
As derape already mentioned, Binding uses reflection. It must use reflection because it cannot know anything about the class you are using. The evaluation will be done at runtime. Since your concrete type Vm got the specified property Number, reflection will return it and Binding class is satisfied. Binding is really flexible as long as the property name is valid.
On the other hand, when you are using the designer, it cannot know which concrete type you will use. Therefore it only allows you to use properties of the common base IVM. If you enter the string manually, design time evaluation will be skipped and input is passed to the binding constructor.
If you want to use designer support, just use the the concrete type or if you don't know the concrete type but need the property Number, simply create a new interface and derive from IMV.
I have 2 variables
Date-Time-Modified which is a Date-Time variables
Is-Deleted variable which is a boolean.
These two variables are found in each class I have and I need to have these variables initialized each time I insert, edit or delete an object from my database. Is there a way to do this?
Use a base class. Add the 2 needed properties (DateTime, IsDeleted). Every derived class now holds this properties. You can set them individually or iterate over the base type to assign a value.
You can also use events to trigger the update automatically. But i think you just want to create an entry and then set its DateTime property to the actual date time.
You also could delegate this task to the database. It will take care of setting this attributes.
An example for my lazy friend ;)
abstract class DatabaseEntryBase
{
public DatabaseEntryBase()
{
// You can initialize properties to a default value here
this.IsDeleted = false;
}
public DateTime ModifiedTime { get; set; }
public bool IsDeleted { get; set; }
}
class Entry : DatabaseEntryBase
{}
static void Main()
{
//-- Do your SQL stuff --//
var newEntry = new Entry();
newEntry.ModifiedTime = DateTime.Now;
newEntry.IsDeleted = false;
}
If you need all instances to hold the same values (e.g. multiple deletes) push them into a collection (here EntryCollection of type List<DatabaseEntryBase>) and iterate over them instead:
public void SetAllItems()
{
foreach (DatabaseEntryBase entry in EntryCollection)
{
entry.ModifiedTime = DateTime.Now;
entry.IsDeleted = [...];
}
}
Using an interface will accomplish the same! It could be named ITaggable and defines this two properties as a contract.
Have a base class that has these members and then have the other classes extend that one.
Then have a method on the base that initalises them. Then call that method on the inserts and such.
base.InitialiseVariables()
Is there any other way to just initialize them without the need of
calling a method?
Probably another approach for this is Aspect-Oriented Programming. For example, PostSharp.
Code will look something like this:
[UpdateTimestamp]
public void InsertProduct(Product product)
{
// Your logic here
}
So i have this property in my partial class overriding the property of my POCO
public new double PaidOvertime
{
get
{
if (!InHoures)
{
return Math.Round(base.PaidOvertime/ 7, 2);
}
else
{
return base.PaidOvertime;
}
}
set
{
if (!InHoures)
{
base.PaidOvertime = value * 7;
}
else
{
base.PaidOvertime = Math.Round(value, 2);
}
statsChanged();
}
}
The thing is, when it come to saving, EF save the value of this property. I would like EF to save the value of the base property or the private variable behind the base property.
Is ther a workaround or something that im missing?
PS : when i say 'saving' i mean saving to the DB
I expect you are using some inheritance mapping otherwise it should not work at all.
Once you use new in derived class you are telling .NET that this is the implementation you want to use every time it works with your class instance. The base implementation is used only if you cast class to base type and work with it as with base type - the question is if this works with EF.
Simply don't do that. new keyword in method and property declaration is something you should use only if you have control over all code using your object. Otherwise you never know which implementation will be called. EF is not your code.