I have set the objct of a class as the datasource of the CR. All the string fields appear in the Fields Explorer in the design alright. But what happen to the numeric or datetime fields? How do I bring them?
public class ClsOutDocket
{
public string RegistrationNo { get; set; }
public double? WeightIn { get; set; }
public DateTime? DateIn { get; set; }
public string TimeIn { get; set; }
}
Unfortunately CrystalReport does not support Nullable<T> and both DateIn and WeightIn fields are nullables.
If it's applicable in your case what you can do is to publish two extra properties that map null to a value, like this:
public double _WeightIn
{
get
{
if (WeightIn == null)
return Double.NaN;
return (double)WeightIn;
}
set
{
if (value == Double.NaN)
WeightIn = null;
else
WeightIn = value;
}
}
Of course this will make your class pretty "dirty" and unless you're using a model class to pass data to the report this may be a problem. You may consider to add this attribute to hide that property in the VS editor:
[EditorBrowsable(EditorBrowsableState.Never)]
Do not forget that CR will see the "fake null" value (Double.NaN and DateTime.MinValue) and because it doesn't know they're special values it'll use them as they are. If this is a problem (or you can't use a proper null value) then you'll need to change your reports to handle this special cases.
Related
How do I hide the Base64EncodedCertificate property from viewing in IntelliSense?
I tried those following attribute options and they don't work.
public class ThirdParty
{
private string _Base64EncodedCertificate = null;
public Guid ThirdPartyId { get; set; }
// Notice: Allowed in source code use but not allowed in EFCore (EFCore doesn't support this).
[NotMapped]
public X509Certificate2 Certificate
{
get { return (_Base64EncodedCertificate == null ? null : new X509Certificate2(Convert.FromBase64String(_Base64EncodedCertificate))); }
set { _Base64EncodedCertificate = (value == null ? null : Convert.ToBase64String(value.GetRawCertData())); }
}
// Notice: Not allowed in Source code but is used by EFCore (EFCore limitation workaround).
[Browsable(false)]
[Bindable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
public string Base64EncodedCertificate
{
get { return _Base64EncodedCertificate; }
private set { }
}
public string RawData { get; set; }
public DateTime CreatedDate { get; set; }
}
You didn't mark the question as ef related, but from the comment on the property in the source code -
// Notice:Not allowed in Source code but is used by EFCore (EFCore limitation workaround).
if i get it right, you're using it only for queries / insert / update, and if this is the case you can hide the member using shadow properties or backing fields without public properties
Maybe you have ReSharper installed? Then try to look this option:
I've read a bunch about auto implemented properties but I still don't quite get it. I have and entity:
public class News
{
public int NewsId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime Date { get; set; }
}
Now I don't want the user to set date himself every time a new entity of News type is created. I want the record to be saved automatically with the datetime it's created. Thinking about it I suggest that it's enough to just modify the set for my property to something like :
public DateTime Date
{
get;
set
{
Date = DateTime.Now;
}
}
But reading about the topic I saw that the standard way is to create private variable and use it instead in the implementation. That's where I get a little bit lost.
private DateTime _date = null;
public DateTime Date
{
Well I'm not sure for the getter and setter implementations. It seems reasonable to have something like : set { _date = DateTime.Now;} and I have no idea how to deal with the get part since I want this data to be fetched from the database so something like : get {return _date;} doesn't make much sense to me even though almost every example with auto implementedset` returns the private variable. But I think that if the property is an entity this is not making a lot of sense.
Some ways to return the current date:
public DateTime Date { get { return DateTime.Now; } }
or
public class News
{
public News()
{
Date = DateTime.Now;
}
public DateTime Date { get; private set; }
}
The first one will always return the current date/time, even if that instance was created some time ago. The second one will return the date/time the instance was created. Both prevent the user from setting that Date value.
You could add a constructor to your class and then initialize there your property.
public class News
{
// properties goes here
public News()
{
Date=DateTime.Now;
}
}
A far better constructor would be the following
public News(int newsId, string title, string content)
{
NewsId=newsId;
Title=title;
Content=content;
Date=DateTime.Now;
}
That way you could create an object of type News in a single line of code.
News news = new News(1,"title1","whatever");
Don't touch the getter and setter! They are auto generated from a template and will be overridden every once and a while. Instead, as you might have noticed the generated entities are declared partially, create a partial class and declare a constructor there that sets the _date or Date of you r entity to DateTime.Now on construction (just as you desired).
public partial class News
{
public News()
{
this.Date = DateTime.Now;
}
}
I've been looking into rules engines and such, but I really am not sure where to start. This is more for experimentation, but I'd like to implement something like this for work in the future. Basically, I have an application where a user submits a form and populates a POCO object with several properties. I want the administrator of the application to be able to define rules based on the properties of said object and store them in a relational database. When the form is submitted, I would then make a decision based on the user defined rules. For example, the admin can go into the application and define rules like following:
if (typeID == 4 && request.benchMarkScore < 10) {
request.denied = true;
request.denyReasons.Add("Score too low for this product");
}
Here's my POCO Object example:
class Request
{
public int benchMarkScore { get; set; }
public int typeID { get; set; }
public double rate { get; set; }
public bool isEligable { get; set; }
public bool denied { get; set; }
public List<string> denyReasons { get; set; }
public Dictionary<string, double> adjustments;
}
Granted I know this is an overly simplified example, but I come across many situations where I users could benefit from this functionality in my applications. I'm not looking for a complete solution, but instead an idea of where to start.
There are a number of ways you could go about this. One suggestion would be to leverage reflection itself, and allow admins to apply a rule. I'm going to keep this simple, but a rule would consist of:
A bunch of properties, operands, and values
The reason(s) for denial.
So let's define that. I am going to keep this simple and just handle equality, you can define additional ones:
public enum Operand
{
Equals
}
Now, we can define an interface called IRule. I am defining an interface so that in the future, you could potentially put special, more complicated, rules in.
public interface IRule<TPOCO> where TPOCO : class
{
bool IsValid(TPOCO poco);
}
And now we'll define our Rule class (Note: this doesn't handle indexed properties):
public class PropertyCompareRule : IRule<Request>
{
private sealed class PropertyCompare
{
public string PropertyName {get; set; }
public Operand Operand {get; set; }
public object Value {get; set;}
public string Reason {get; set; }
}
private List<PropertyCompare> _comparers = new List<PropertyCompare>();
public bool IsValid(Request poco)
{
bool isValid = true; // let's be optimistic!
PropertyInfo[] properties = poco.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where((property) => property.GetIndexParameters().Length == 0 && property.CanRead).ToArray();
foreach(var property in properties)
{
foreach(var comparer in _comparers)
{
bool localIsValid;
if(comparer.PropertyName == property.Name)
{
object val = property.GetValue(poco, null);
switch(comparer.Operand)
{
case Operand.Equals:
{
localIsValid = object.Equals(val, property.Value);
break;
}
}
if(!localIsValid)
{
poco.denyReasons.Add(comparer.Reason);
isValid = false;
}
}
}
}
return isValid;
}
public void AddComparer(string propertyName, Operand op, object value, string reason)
{
_comparers.Add(new PropertyCompare() { PropertyName = propertyName, Operand = op, Value = value, Reason = reason });
}
}
It wouldn't be difficult for you to be able to persist the property name, operand, and value details in a database or other such storage. Assuming we fleshed out our enum above, we could conceivably do:
PropertyCompareRule rule = new PropertyCompareRule();
rule.AddComparer("typeID", Operand.Equal, 4, "Reason 1");
rule.AddComparer("benchMarkScore", Operand.LessThan, 10, "Reason 2");
bool valid = rule.IsValid(somePocoInstance);
Edit: Some notes
I use a localIsValid rather than bailing out at the first opportunity. You can change this if you want, but the idea is that it allows a single rule to have multiple points of deniability. This may or may not be what you wish - but it's easy enough to refactor the code so that it bails out the moment a single property comparison fails.
This is a nit-pick, but generally C# style-guidlines dictate properties shouldn't be camel-caps... but that's entirely up to you at the end of the day :)
As I understand you, you are looking for some kind of a scripting system for business rules. I found this blog post where some scripting environment are mentioned.
You can also create assemblies on the fly like mentioned here: https://stackoverflow.com/a/4181855/1229622.
I'm currently finishing work on object change log functionality and would like to polish few things. Since we have a lot of web forms/reports where historical data should appear, I'm wondering if there is a way to implement that without changing controls/reports.
Currently, I have this situation:
public class Foo {
public string Property1 { get; set; }
public DateTime CreatedDate { get; set;}
public string GetHistoricalValue(string propertyName)
{
HistoryHelper historyHelper = CreateHistoryHelper(this);
return historyHelper.GetHistoricalValue(propertyName, CreatedDate);
}
...
public class HistoryHelper {
public string GetHistoricalValue(string propertyName, DateTime date) {
...
So, when someone wants to fetch historical data for Property1:
string historicalValue = fooInstance.GetHistoricalValue("Property1");
It's obvious that this approach requires a lot of changes in current application.
Is there a way to make Foo class returns historical value when I access Property1 in regular way:
string historicalValue = fooInstance.Property1;
Something like dynamically generating subclass with overriden properties or some other solution?
Is this possible?
INITIAL ANSWER
Something like this:
public class Foo {
public bool HistoricalMode { get; set; }
private string _property1;
public string Property1 {
get {
if (HistoricalMode) {
return GetHistoricalValue("Property1");
} else {
return _property1;
}
set {
if (HistoricalMode){
throw new NotSupportedException("Updates not possible in historical mode.");
} else {
_property1 = value;
}
}
}
public DateTime CreatedDate {
get {
// Similar pattern as above
}
set {
// Similar pattern as above
}
}
public string GetHistoricalValue(string propertyName) {
HistoryHelper historyHelper = CreateHistoryHelper(this);
return historyHelper.GetHistoricalValue(propertyName, CreatedDate);
}
}
Basically the idea is to keep a boolean in your objects which indicates in the object is in 'history mode'. If so, use your helper method. If not, normal properties getters/setters apply.
UPDATE
The solution to this question I think would require a change in your framework (if you have a single framework for all your applications). I would seek the solution in the way you are loading your objects. Hopefully you can detect when an object is required in 'historical mode' and when in 'normale mode'. Where you now 'just read' the object (record) from the database, in historical mode you need to compose the original object (from when the change happened) from your change log functionality. That way, all your current application can (hopefully) stay the way they are. The 'only' change you need to do is at the repository class.
This is all just speculation btw.
Can you easily affect how Foo instances are created? If so, you can for example create derived class HistoricalFoo : Foo, make Property1 virtual and use its getter to change its behaviour. Then use HistoricalFoo whenever you need historical data. It is not a very clean object model, but can get the job done.
public class Foo
{
protected string _property1;
public virtual string Property1
{
get { return _property1; }
set { _property1 = value; }
}
public DateTime CreatedDate { get; set;}
/* ... */
}
public class HistoricalFoo : Foo
{
public override string Property1
{
get
{
return GetHistoricalValue("Property1");
}
}
}
If this is not applicable, it's possible to embed some decision logic into the Property1 getter. In this scenario, you would have to change the internal state of the Foo instance - for example by setting a boolean flag IsInHistoryMode. Changing object states can be very tricky though, expecially in multithreaded environment.
public class Foo
{
public bool IsInHistoryMode { get; set; }
protected string _property1;
public virtual string Property1
{
get
{
if(IsInHistoryMode)
{
return GetHistoricalValue("Property1");
}
return _property1;
}
set
{
_property1 = value;
}
}
public DateTime CreatedDate { get; set;}
/* ... */
}
I have a business class that contains many properties for various stock-exchange price types. This is a sample of the class:
public class Prices
{
public decimal Today {get; set;}
public decimal OneDay {get; set;}
public decimal SixDay {get; set;}
public decimal TenDay {get; set;}
public decimal TwelveDay {get; set;}
public decimal OneDayAdjusted {get; set;}
public decimal SixDayAdjusted {get; set;}
public decimal TenDayAdjusted {get; set;}
public decimal OneHundredDayAdjusted {get; set;}
}
I have a legacy system that supplies the prices using string ids to identify the price type.
E.g.
Today = "0D"
OneDay = "1D"
SixDay = "6D"
//..., etc.
Firstly, I load all the values to an IDictionary() collection so we have:
[KEY] VALUE
[0D] => 1.23456
[1D] => 1.23456
[6D] => 1.23456
...., etc.
Secondly, I set the properties of the Prices class using a method that takes the above collection as a parameter like so:
SetPricesValues(IDictionary<string, decimal> pricesDictionary)
{
// TODAY'S PRICE
string TODAY = "D0";
if (true == pricesDictionary.ContainsKey(TODAY))
{
this.Today = pricesDictionary[TODAY];
}
// OneDay PRICE
string ONE_DAY = "D1";
if (true == pricesDictionary.ContainsKey(ONE_DAY))
{
this.OneDay = pricesDictionary[ONE_DAY];
}
//..., ..., etc., for each other property
}
Is there a more elegant technique to set a large amount of properties?
Thanks,
j
Instead of using a string-to-decimal mapping and checking the dictionary repeatedly, use a delegate mapping/extension method:
public static class PriceConverter
{
private static readonly Dictionary<string, Action<Prices, decimal>> setters =
CreateSetterDictionary();
public static void SetPrice(this Prices p, string id, decimal newPrice)
{
Action<Prices, decimal> setter;
if (setters.TryGetValue(id, out setter))
setter(p, newPrice);
}
private static Dictionary<string, Action<Prices, decimal>>
CreateSetterDictionary()
{
var dic = new Dictionary<string, Action<Prices, decimal>>();
dic.Add("0D", (p, d) => p.Today = d);
dic.Add("1D", (p, d) => p.OneDay = d);
// etc.
return dic;
}
}
Then you can write prices.SetPrice("0D", 1.23456).
If you like, add a throw statement at the end of the SetPrice method to handle cases where the id doesn't match anything.
I would put the string variables into constants, rather than declare them every time you run the method:
private const string ONE_DAY = "D1";
If you expect the collection parameter to contain all or most of the possible values, then your code is probably cool. If you expect that the dictionary will have a small subset of the possible values, it might be more efficient to use a foreach loop and a switch statement to set values, rather then do a lookup for every possible value every time. It just depends on how many values you need to deal with and how many you get in each method call.
Define a dictionary of properties in the constructor e.g.
private Dictionary<int, PropertyInfo> propertyDictionary = new ...
MyClass()
{
this.propertyDictionary.Add(0, this.GetType().GetProperty("FirstProperty");
...
}
then access using an indexed property
decimal this[int index]
{
get
{
PropertyInfo property;
if (this.propertyDictionary.TryGetValue(index, out property))
{
// Not sure I remember the arguments right here:
property.SetValue(this, new object[] { value });
}
set
{
// Similar code
}
}
You could later on improve this code by automatically parsing the properties in the constructor using reflection,
adding all properties with an attribute that tells you what the id is.
(Instead of adding them manually in the constructor).
Just an idea:
interface IPrices_As_String{
string OD { get; set; }
// other properties here...
}
interface IPrices{
decimal Today{get; set;}
}
class Prices : IPrices, IPrices_As_String{
public decimal Today { get; set; }
public string IPrices_As_String.OD {
get { return this.Today.ToString(); }
set {
if(!String.IsNullOrEmpty(value)){
this.Today = decimal.Parse(value);
}
}
}
}
Then when I am setting the values from the legacy system, I will use the Prices class on the interface as IPrices_As_String like:
IPrices_As_String obj = new Prices();
// set values from the legacy system
IPrices obj2 = obj as IPrices; // will give me the correct object..
.
HTH.
The way I see it, you have a few options, depending on your skills, the way you are allowed to change the current POCO's or other classes:
If you must use a dictionary, create a similar dictionary which maps the "0D" etc to the OneDay names. Loop through the dictionary and assign using simple reflection.
If you can change the way the data is read, have the dictionary read with OneDay etc, instead of the "0D", which is only applicable to the external application.
Create an attribute, LegacyKeyAttribute, augment your POCO gettors/settors with this attribute. Now it becomes trivial: loop through the properties of the POCO to find the correct property for your current legacy key.
The last option requires a bit more understanding of C# than many average programmers know: writing and using attributes and reflection. However, in the end it's the cleanest and easiest solution (I'll try to come up with an example).
UPDATE: here's a little example. Meanwhile, many improvement suggestions have been posted, but none still uses attributes, while your case seems ideal. Why? It poses the least burden on existing code, I believe, and it makes reading and understanding your code even easier.
Usage:
// any price:
Prices prices = new Prices();
prices.SetPriceByLegacyName("0D", 1.2345M);
// or, your loop becomes a bit easier:
SetPricesValues(IDictionary<string, decimal> pricesDictionary)
{
foreach(string key in pricesDictionary.Keys)
{
// assuming "this" is of type Prices (you didn't specify)
this.SetPriceByLegacyName(key, pricesDictionary[key]);
}
}
The implementation:
// the simplest attribute class is enough for you:
[AttributeUsage(AttributeTargets.Property)]
public class LegacyNameAttribute : Attribute
{
public string Name { get; set; }
public LegacyNameAttribute(string name)
{
this.Name = name;
}
}
// your Prices POCO class becomes easier to read
public class Prices
{
[LegacyName("0D")] public decimal Today { get; set; }
[LegacyName("1D")] public decimal OneDay { get; set; }
[LegacyName("6D")] public decimal SixDay { get; set; }
[LegacyName("10D")] public decimal TenDay { get; set; }
[LegacyName("12D")] public decimal TwelveDay { get; set; }
[LegacyName("1DA")] public decimal OneDayAdjusted { get; set; }
[LegacyName("6DA")] public decimal SixDayAdjusted { get; set; }
[LegacyName("10DA")] public decimal TenDayAdjusted { get; set; }
[LegacyName("100DA")] public decimal OneHundredDayAdjusted { get; set; }
}
// an extension method to ease the implementation:
public static class PricesExtensions
{
public static void SetPriceByLegacyName(this Prices price, string name, decimal value)
{
if (price == null)
throw new ArgumentException("Price cannot be null");
foreach (PropertyInfo prop in price.GetType().GetProperties())
{
LegacyNameAttribute legNameAttribute = (LegacyNameAttribute)
Attribute.GetCustomAttribute(prop, typeof(LegacyNameAttribute));
// set the property if the attribute matches
if (legNameAttribute != null && legNameAttribute.Name == name)
{
prop.SetValue(price, value, null);
break; // nothing more to do
}
}
}
}
That's all there is to it. Even with all the added lines, it may well be that your total line count becomes less. But more importantly, it becomes easier to maintain and use.