Say I have defined a custom AdapterElement : ConfigurationElement with properties Type, Name and Version. Since Name and Version uniquelly identifies the Type property, I would like to enforce the configuration file to have one of the following structures:
<adapter type="TypeOfAdapter"/>
<adapter name="NameOfAdapter" version="VersionOfAdapter"/>
I could easily mark those three properties with IsRequired = false and let users specify the combination the want. However, the following combinations are not valid and I would like to forbid them:
<adapter type="TypeOfAdapter" version="VersionOfAdapter"/>
<adapter type="TypeOfAdapter" name="NameOfAdapter"/>
Is there any easy way of achieving this?
I had to do a bit of reading around to find answers on this one.
How about adding a PostDeserialise check for validity to your AdapterElement class?
protected override void PostDeserialize()
{
bool isValid = Type != null && Name == null && Version == null
|| Type == null && Name != null && Version != null;
if (!isValid)
{
throw new ArgumentException("Must specify either Type or Name and Version");
}
base.PostDeserialize();
}
According to a blog I found there is no more obvious way of verifying validity of Multiple Attributes on a single configuration section - but it appears to be true for configuation elements too.
Related
I have a problem understanding, and living with, the excessive use of bang operators in dart/flutter.
Consider this example:
if(model != null && model!.someValue != null) {
print(model!.someValue!);
}
The first condition check is verifying that the model is not null. In the second condition I have to put in a bang operator after model, else the compiler gives me an The property 'someValue' can't be unconditionally accessed because the receiver can be 'null' error. But why is this necessary? I´ve just checked the variable! And same goes for the print(model!.someValue!); line.
Another example where I have these classes:
class GeoPosition {
double lat = 0;
}
class Wrapper {
GeoPosition? position;
}
...
Wrapper wrapper = Wrapper();
wrapper.position = GeoPosition();
wrapper.position!.lat = 1;
Now why do I need to put this bang operator (or ? operator) after position? I´ve just created a new instance of GeoPosition in the Wrapper instance - position cannot be null.
My best guess is that the compiler cannot see or understand the current context of the class. But in Typescript the linter is smart enough to know when these operators are not necessary.
I know that I can create local variables from the properties that I am trying to access, but this would be just as ugly ;)
So why are ! and ? necessary in these (and many other) situations? And is there anything I can do about it?
This is what happens with nullable properties (hence the message you get). It is explained here: Understanding null safety: Working with nullable fields.
You should be able to work around this issue by declaring the field as late, as in
class Wrapper {
late GeoPosition position;
}
Wrapper wrapper = Wrapper();
wrapper.position = GeoPosition();
wrapper.position.lat = 1;
This will remove the need to add a bang to every access to position The compiler will add a non-null check at appropriate places. Of course, the program will fail if you don't assign a non-null value before accessing the field.
If explained in Late variables
Nullable properties of a class can still be null between two access.
For your first example you can extract the variable then check it:
var someValue = model?.someValue;
if(someValue != null) {
print(someValue); // not null
}
For your second example an elegant way will be the .. operator :
Wrapper wrapper = Wrapper();
wrapper. Position = GeoPosition()..lat = 1;
If you want the GeoPosition to be not null you have to make it not nullable:
class Wrapper {
GeoPosition position;
Wrapper(this.position);
}
You can set the position field final to be immutable.
Be careful with the late keyword, if you forget to init the field you've got a crash like the ! operator.
We are using EF Dynamic filters (ASP.NET MVC 5 app)
https://entityframework-dynamicfilters.net/overview
The filter below is working, but set only once.
builder.Filter("IMultiOrganization", (IMultOrganization d) => ((d.TenantId == GlobalAppVariables.IssuerId) && (d.IsShared == true)) || ((d.IsShared == false && d.AzureObjIdentifier == GlobalAppVariables.AzureObjIdentifier)));
The variables 'IssuerId' and 'AzureObjIdentifier' are dynamic session variables, those are changing all the time. This causes problems and I would like the filter to use those variables straight from the session.
According to the documentation this is caused because this filer isn't a delegate expression.
Filters can be defined on a specific entity class or an interface by providing a specific value, e.g. an IsDeleted filter created on an ISoftDelete interface which will automatically filter those entities by applying the condition "IsDeleted==false".
Filter values can also be provided via a delegate/expression instead of a specific value which allows you to change the parameter value dynamically. For example, a filter can be created on the UserID and provided per HTTP request.
We also use delegate filters what indeed is working fine.
builder.EnableFilter("IMultiTenant", () => GlobalAppVariables.AzureObjIdentifier != null || GlobalAppVariables.IssuerId != Guid.Empty);
But I can't get the first filter work as a delegate expression and need a bit help on that.
I found the solution by using parameters within the filter.
First of all I changed the filter which now supports parameters.
builder.Filter("IMultiOrganization", (IMultiOrganization d, Guid tenantId, string azureId) => (d.TenantId == tenantId && d.IsShared == true) || (d.AzureObjIdentifier == azureId && d.IsShared == false), GlobalAppVariables.IssuerId, GlobalAppVariables.AzureObjIdentifier);
Then I call method below in the db context constructor
private void SetMultiOrganizationFilterParams()
{
if (GetFilterEnabled("IMultiOrganization"))
{
this.SetFilterScopedParameterValue("IMultiOrganization", "azureId", GlobalAppVariables.AzureObjIdentifier);
this.SetFilterScopedParameterValue("IMultiOrganization", "tenantId", GlobalAppVariables.IssuerId);
}
}
Source: https://github.com/zzzprojects/EntityFramework.DynamicFilters#changing-filter-parameter-values
String playerName(String? name) {
if (name != null) {
return name;
} else {
return 'Guest';
}
}
? checks whether name is null or not, then why is special if (name != null) { condition required?
The String? name means that the parameter name is nullable as you can see lower in the code the if statement then checks if your parameter is not null.
Dart docs definition:
If you enable null safety, variables can’t contain null unless you say they can. You can make a variable nullable by putting a question mark (?) at the end of its type. For example, a variable of type int? might be an integer, or it might be null. If you know that an expression never evaluates to null but Dart disagrees, you can add ! to assert that it isn’t null (and to throw an exception if it is). An example: int x = nullableButNotNullInt!
Link to docs
How to make mapping from two different fields? I need to set b.url to a.x.y.z.url if it exists otherwise to a.k.l.m.url:
b.url = exists(a.x.y.z.url) ? a.x.y.z.url : exists(a.k.l.m.url) ? a.k.l.m.url : defaultValue
Expression might help but it will be quite long expression if I check all nested fields for null, like "a != null && a.getX() != null && a.getX().getY() != null && a.getX().getY().getZ() != null && a.getX().getY().getZ().getURL() != null ? a.getX().getY().getZ().getURL() : ..."
Thanks,
Pavel
You can use MapStruct #AfterMapping to gain access to the mapping object.
#AfterMapping
protected void mapUrl(B b, #MappingTarget A a) {
//You will do your logic here
}
Theoretically you could do it via an expression by declaring you Mapper as an abstract class and defining a getUrl(A a) method. They in your expression you could call getUrl(a).
I would suggest to use the #AfterMapping, as it is cleaner (in my opinion)
I'm writing a custom validator that will validate against multiple other form element values. In my form, I call my custom validator like this:
$textFieldOne = new Zend_Form_Element_Text('textFieldOne');
$textFieldOne->setAllowEmpty(false)
->addValidator('OnlyOneHasValue', false, array(array('textFieldTwo', 'textFieldThree')));
My validator will check that only one of those three fields (textFieldOne, textFieldTwo, textFieldThree) has a value. I want to prevent a future developer from accidentally passing the same field twice.
$textFieldOne->addValidator('OnlyOneHasValue', false, array(array('textFieldOne', 'textFieldTwo', 'textFieldThree')));
So far, my validator works perfectly, except when I pass the same field name as the field that has the valiator set on it.
In my validator, you can see that I am checking that the value (of the element with the validator set on it). I'm also checking the values of the other fields that were passed to the validator.
public function isValid($value, $context = null) {
$this->_setValue($value);
$this->_context = $context;
if ($this->valueIsNotEmpty()) {
if ($this->numberOfFieldsWithAValue() == 0) {
return true;
}
$this->_error(self::MULTIPLE_VALUES);
return false;
}
if ($this->numberOfFieldsWithAValue() == 0) {
$this->_error(self::ALL_EMPTY);
return false;
}
if ($this->numberOfFieldsWithAValue() == 1) {
return true;
}
if ($this->numberOfFieldsWithAValue() > 1) {
$this->_error(self::MULTIPLE_VALUES);
return false;
}
}
private function valueIsNotEmpty() {
return Zend_Validate::is($this->_value, 'NotEmpty');
}
private function numberOfFieldsWithAValue() {
$fieldsWithValue = 0;
foreach ($this->_fieldsToMatch as $fieldName) {
if (isset($this->_context[$fieldName]) && Zend_Validate::is($this->_context[$fieldName], 'NotEmpty')) {
$fieldsWithValue++;
}
}
return $fieldsWithValue;
}
My solution is to either...
A. Let the developer figure out there is a certain way to do it.
B. Ignore $value, forcing you to pass all the elements (which isn't much different than the first option).
or C. (if possible) Find the name of the element that called my validator in the first place and ignore it from the list of $fieldsWithValue.
I don't think there is a way to apply a validator on a form without attaching it to an element, but that would be even better, if it were an option.
How can I solve this problem?
Normaly i'd advise against such things, but, in this case I believe a static member in your class would actually provide a good solution to this problem.
With a static member, you can set it to the value in the first time the isValid is called, and check against it in subsequent calls, thus giving you a mechanism for this.
You may want to set this up to use some array in the configuration options, so that you can namespace and allow multiple instances of the validator to exist happily alongside each other for different sets.
The only problem that you really have to decide how to overcome, is where you wish to display the error, as yes the form itself does not take validators. if you want all the duplicates after the first to display an error, it is not so much of a problem.