Fody, propertychanged and setting same value? - fody-propertychanged

Is there any way to configure fody to not check the value which is set to property - I have situations when value is the same and I want property to be set because I have additional logic in property setter that is not invoked.

This is clearly literally years after the original question but for future reference:
This is indeed possible by modifying the options in the FodyWeavers.xml file.
As is shown on the PropertyChanged.Fody wiki, one of the options is called CheckForEquality and can be set to false (it defaults to true). This will prevent Fody from injecting equality checking code. The FodyWeavers.xml file could now look as follows:
<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
<PropertyChanged CheckForEquality='false'/>
</Weavers>
As noted in the comments there is also the possibility to do this per property via the DoNotCheckEquality attribute e.g.
[ImplementPropertyChanged]
public class Person
{
[DoNotCheckEquality]
public string Name { get; set; }
}
See wiki/Attributes

Related

Antlr4 contextSuperClass to add custom properties for a two pass interpreter

I have just discovered contextSuperClass and have been experimenting with using it to provide scope annotations when building a symbol table in a first pass (I have a forward reference DSL).
I set the option in the grammar:
options {
tokenVocab=MyLexer;
language = CSharp;
contextSuperClass = interpreter.MyParserRuleContext;
}
and I have a class that derives from ParserRuleContext:
public class MyParserRuleContext : ParserRuleContext
{
public MyParserRuleContext()
{ }
public MyParserRuleContext(ParserRuleContext parent, int invokingStateNumber) : base(parent, invokingStateNumber)
{
}
public IScope ContextScope { get; set; }
}
So far so good. I use ParseTreeWalker with a listener (Enter/Exit methods) to walk the tree for the 1st pass and build the symbol table adding local scopes, etc into my ContextScope custom property.
The first issue is of course after the symbol table pass I am at the end of the token stream - the tree is walked.
The 2nd parse uses a visitor to evaluate the final result.
I have two questions:
How do I "reset" the parser so that it is at the root again without loosing scopes I have added into my custom property?
The second question is broader, but similar. Is this even a reasonable way to add scope annotations to the parse tree?
I have previously tried to use ParseTreeProperty<IScope> to add scope annotations, but the problem is similar. During the 2nd phase, the context objects provided in the visitor are not the same objects added to ParseTreeProperty<IScope> concurrent dictionary from the 1st pass - so they are not found. Between the 1st & 2nd passes I have only found parser.reset() as a way to start the parser over, and (of course) it appears to fully reset everything and I loose the any state I created in the 1st pass.
I am likely missing completely missing something here - so any help to put me in the right direction will be greatly appreciated.

Automapper isn't using extension methods for mapping

I have automapper setup like this
services.AddAutoMapper(typeof(MappingAssembly).Assembly, typeof(AssemblyWithExtensionMethods).Assembly);
And in one of my profiles
public class UserModuleMapper : Profile {
public UserModuleMapper() {
IncludeSourceExtensionMethods(typeof(UserGroup));
CreateMap<UserGroup, UserGroupDto>(MemberList.Destination);
}
}
And I have defined the extension method as
public static List<string> GetRoleNames(this UserGroup group) {
return group.UserGroupRoles.Select(x => x.Role.Name).ToList();
}
I have a property on DTO defined as
public List<string> RoleNames { get; set; }
As per the automapper documentation, I have made the following assumptions:
IncludeSourceExtensionMethods, which include extension methods while mapping
while mapping it will also look for methods with prefix Get
But when I validate the automapper extension I get error for unmapped property
Unmapped properties: RoleNames
What is missing in my configuration, automapper should detect the extension method.
I have tried (a) remove GET from the method name, but still does not work (b) moving CreateMap before or after the IncludeSourceExtensionMethods to see if sequence matters, but none of it helped.
With in few minutes after posting the question I got the answer by carefully looking at this issue on Github
The issue was with below statement
IncludeSourceExtensionMethods(typeof(UserGroup));
the type mentioned here should be of extension class
IncludeSourceExtensionMethods(typeof(UserGroupExtensions));
Not deleting the question, as it might help someone in future.

How do you get ServiceStack.ToJson to *sometimes* ignore properties?

I have a ServiceStack DTO:
[Route("/images", "POST")]
public class PostImageCommand
{
public string Notes { get; set; }
public byte[] Image { get; set; }
//other properties removed for brevity
}
I also have a part in my code that logs messages using log4net. I do this by serializing the command. For example, I just do this:
var command = new PostImageCommand(){
//set properties
};
var commandJson = command.ToJson();
MyLogClass.Log(commandJson);
The problem: The Image byte array can get pretty large. I do not want to serialize this property when logging, or else my log will be filled with large amounts of image data.
I tried putting the [IgnoreDataMember] attribute on the Image byte[] in the DTO. However, that causes the build to fail without Visual Studio saying why. I can put the Attribute on the Image property, but when I try to build I see this:
No reason why the build failed, just these messages. The Output tab only says "The operation was canceled".
My question: What is the easiest way to ignore a DTO property from being serialized in my situation?
This previous answer lists the different ways to ignore properties in ServiceStack.Text. But really if you just want to ignore the property from being logged you can just set the property to null then restore it, map it to a different model with just the types you want serialized using the built-in AutoMapping tools, Use ToObjectDictionary() extension method to serialize your model into a dictionary then remove the items you don't want logged.
The issue you're having with the [IgnoreDataMember] attribute is because you haven't referenced the System.Runtime.Serialization .NET Framework Assembly.

asp.net 5: Bind attribute with Include parameter - include is not a valid named attribute argument

I write code from the article and and there is:
public IActionResult Create([Bind(Include="Imie,Nazwisko,Stanowisko,Wiek")] Pracownik pracownik)
{
blablablab
}
I want to compile but it shows error.
include is not a valid named attribute argument.
But in the internet I saw a code similar to my code.
Someone explain to me what's going on?
Of course, I am using asp.net 5.
In Asp.Net Core, the Include property no longer has a setter. You need to pass the list of bound properties using the constructor:
public BindAttribute(params string[] include)
{
Include = include;
}
And in your case:
public IActionResult Create([Bind("Imie","Nazwisko","Wiek")] Pracownik pracownik)

Properties files to control form inputs based on roles

The requirements of the application that I'm building demands that user roles are to be dynamic, they will be stored in the database, and they will also be mapped to functionalities (forms) of the application, also stored in the database.
Restricting a role from accessing a specific page won't be difficult, but the requirements also states that form inputs must be customized based on roles, which means, an input can be mandatory or not, visible or not, read-only or not based on the role.
My approach to control these restrictions is based on creating a property file for each role, which will store all the inputs of all the forms in the application, as keys, and a long string as value in which we define the state of the input, like the following:
user-inputs.properties
# form.input=mandatory:visibility
searchBooks.bookName=true:true
searchBooks.bookCategory=false:true
searchBooks.authorName=false:false
admin-inputs.properties
searchBooks.bookName=true:true
searchBooks.bookCategory=false:true
searchBooks.authorName=false:true
And then do some magic Java code, whenever a form is accessed, read its inputs properties from the file of the specific user role, and parse the values so I could provide the right value for the rendered="" and required="" attribute of an <h:inputText/>.
This could be a solution, but the inputs of the application are much more than a book name and category, means I will be putting lots of required and rendered attributes which will make JSF pages look ugly with huge amount of variables in the managed bean.
Is there a better approach/framework/solution to my issue?
I think that you are in the right way, and i will continue using your approach which consists of creating multiple property files, one for each user, except that we will not use a any "huge amount of variables
in the managed bean".
So, the first step consists on managing multiple resource properties using a single resource bundle prefix ( the <var></var> in <resource-bundle>), in the second step we will see how to switch between those files, and in the last step we will read from property file using JSTL.
Managing multiple property files:
We start by defining our ResourceBundle in the faces-config file:
<application>
<resource-bundle>
<base-name>UserMessages</base-name>
<var>msgs</var>
</resource-bundle>
</application>
UserMessages is a ResourceBundle where we will implement the logic that allow us to switch between our property files (assuming that yourpackage.user-inputs is the fully qualified name of your user-inputs.properties):
import java.util.Enumeration;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
public class UserMessages extends ResourceBundle {
public UserMessages() {
// we are loading user-inputs.properties as the default properties file
setParent(getBundle("yourpackage.user-inputs", FacesContext.getCurrentInstance()
.getViewRoot().getLocale()));
}
#Override
protected Object handleGetObject(String key) {
// we could just return parent.getObject(key) but we want to respect JSF recommandations
try {
return parent.getObject(key);
} catch (MissingResourceException e) {
return "???" + key + "???";
}
}
#Override
public Enumeration<String> getKeys() {
return parent.getKeys();
}
// this is the method that will allow us to switch between our .properties
public void setResourceBundle(String basename) {
setParent(getBundle(basename, FacesContext.getCurrentInstance()
.getViewRoot().getLocale()));
}
}
Switching between property files:
In order to switch from a property file to another we will need to use the method setResourceBundle(String basename) that we just declared in our class above, So in the managed bean where you are declaring your business logic and where you are intending to switch files depending on the user's role, you need to inject the bundle, like:
//don't forget adding getters and setters or you end with NullPointerException
#ManagedProperty("#{msgs}")
private UserMessages userMesssages;
Then, to switch to another file (admin-inputs.properties), just use it like this:
//yourpackage.admin-inputs is the fully qualified name
userMesssages.setResourceBundle("yourpackage.admin-inputs");
NB: You can inject the bundle in that way (above) only in request scoped beans, to use it in broader scopes please see: Read i18n variables from properties file in a Bean
Now, as we can switch easily from the user-inputs to the admin-inputs, the last step is the easiest one.
Parsing the property file:
The bad news, is that when using this approach you will need to add rendered="" and required="" attribute to every input you are willing to manage (but don't forget that the good ones was that you will not need to manage variables in managed beans ;) ).
First, you need to add JSTL namespaces declaration on the top of your xhtml file:
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
you can find more about JSTL functions in the javadocs, regarding the function substringAfter:
Returns a subset of a string following a specific substring.
Example:
P.O. Box: ${fn:substringAfter(zip, "-")}
The function substringBefore:
Returns a subset of a string before a specific substring.
Example:
Zip (without P.O. Box): ${fn:substringBefore(zip, "-")}
Second, as the first part of your String represents the required attribute:
//Returns the substring of msgs['searchBooks.authorName'] before the first occurrence of the separator ':'
required="${fn:substringBefore(msgs['searchBooks.authorName'], ':')}"
and the second part:
//Returns the substring of msgs['searchBooks.authorName'] after the first occurrence of the separator ':'.
rendered="${fn:substringAfter(msgs['searchBooks.authorName'], ':')}"
See also:
JSF Internationalization f:loadbundle or through faces-config:
Performance point
Difference between by Application#getResourceBundle() and ResourceBundle#getBundle() in JSF 2.0
How to remove the surrounding ??? when message is not found in
bundle
Context Sensitive Resource Bundle entries in JavaServer Faces
applications – going beyond plain language, region & variant
locales

Resources