in our architecture, we have a bunch of models like this
public class UserModel
{
public string FirstName {get;set;}
}
and since we're using MvvmCross for our view models, we need our properties to look like this
public class UserViewModel: MvxViewModel
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set { _firstName = value; RaisePropertyChanged(() => FirstName); }
}
}
Now I've already got an R# template to write my own mvx properties by simply typing propmvx, but I still need to type in the type and the name.
I'm wondering if there's a way to setup a custom conversion template in order to have the alt + enter context menu to have a second option... something like
[T]o property with backing field
To [M]vx property with backing field
This is possible, even without creating any custom plugins or patterns, by using ReSharper Annotations. I have recently recorded a webinar with JetBrains, demonstrating exactly how to solve this with annotations. You can watch it here.
Short answer: the method
public void RaisePropertyChanged<T>(Expression<Func<T>> property)
of MvxNotifyPropertyChange.cs needs to be annotated with the NotifyPropertyChangedInvocatorAttribute, and then you could simply Alt-Enter on the property, and change it to a Property with change notificaton.
Now, since you can't (or don't want to) modify the source code of MvvmCross, you could apply those annotations externally, via XML. Take a look at the ExternalAnnotations directory, located in your ReSharper installation directory. It contains a bunch of external annotations for other MVVM frameworks. It's a simple XMLDoc format, so you could create an XML for MvvmCross and write the appropriate methods there. After that, save the file under a directory MvvmCross (or however the assembly is called), reload your solution, and it should just work!
For more information, please watch my webinar (link above), or JetBrains help
Here's an External Annotations file that will work with that method.
Cirrious.MvvmCross.ExternalAnnotations.xml
<?xml version="1.0" encoding="utf-8"?>
<assembly name="Cirrious.MvvmCross">
<member name="M:Cirrious.MvvmCross.ViewModels.MvxNotifyPropertyChanged.RaisePropertyChanged``1(System.Linq.Expressions.Expression{System.Func{``0}})">
<attribute ctor="M:JetBrains.Annotations.NotifyPropertyChangedInvocatorAttribute.#ctor" />
</member>
</assembly>
And here it is in action:
Related
I have some data specific to each razor view and and i do not want to hard-code it to each view. So, i want to add view related compile-time data to each view.
Custom attributes do not work for me because we cannot add custom attributes to razor views.
I do not want to re-fetch/populate this data from the data source(dictionary etc.) for each request or when view reached.
So, is there any way to attach data to each view at once throughout the life time of asp.net application?
Note
Actually i want to add scripts/styles generated by webpack for each view statically. Their links include hash values so they change when source scripts/styles change. So, i just want to get them added to each view only once(equivalent to typing them into view) through out the asp.net application, not every time a view loads.
I created a demo application for you here.
You will want to use your appsettings.json file, and inject your settings into your view.
In my appsettings.json I added a section called "ViewConfiguration":
"ViewConfiguration": {
"ExampleKey": "ExampleValue"
}
Your various values will need to go into your ViewConfiguration section.
For example where I have ExampleKey, you will use a generic name like "IndexPageStyleSheet", and where I have ExampleValue, you will need to update each release with the new stylesheet path. This will only need to be updated when the filename changes.
I then created a ViewConfiguration class which stores all of the values from the appsettings.json file.
You will need to create one property per configuration line, and ensure that the name of the property matches the name of the key in your appsettings.json.
For example where my appsettings.json has ExampleKey, my ViewConfiguration class also has an ExampleKey.
public class ViewConfiguration {
public string ExampleKey { get; set; }
}
In your Startup.cs you will need to tell your IOC container to load your configuration values into your configuration object.
In my Startup.cs, my ConfigureServices method loads my "ExampleValue" into ViewConfiguration.ExampleKey automatically.
public void ConfigureServices(IServiceCollection services) {
// This line is the magic that loads the values from appsettings.json into a ViewConfiguration object.
services.Configure<ViewConfiguration>(Configuration.GetSection("ViewConfiguration"));
services.AddMvc();
}
Now, in my _ViewImports.cshtml I inject my ViewConfiguration object so that I don't need to inject it into every single page. This can be anywhere in the _ViewImports.cshtml file. If you only want to inject specific configuration per folder, you can create a new _ViewImports.cshtml file per folder and inject different configuration objects into each one. It's flexible.
#using Microsoft.Extensions.Options;
#* Please rename this variable to something more appropriate to your application: *#
#inject IOptions<ViewConfiguration> InjectedViewConfig
Now, in any page, you can simply reference the property in your ViewConfiguration object.
For example in my Index.cshtml, I reference the ViewConfiguration.ExampleKey property by referencing the strongly typed property on InjectedViewConfig.Value, and it outputs "ExampleValue" on the page.
This value could just as easily be injected into a script or css link tag as the name of a file. It's very flexible.
<h1>Value: #InjectedViewConfig.Value.ExampleKey</h1>
With further research, you will be able to inject these values from any configuration source, such as Azure application settings or Azure Key Vault. Please see this article for more details.
If you are using mvc, you can create models and add it into the views. Since you don't want to recreate for each view, you can create readonly variables.
static readonly MyModel ModelData = new MyModel { PropName = "Hello" };
public IActionResult Index () => View(ModelData);
In your view you can now strongly type the value. If you are looking to use MVVM, you can refer to ViewModel concept still exists in ASP.NET MVC Core?
Implementing IFileProvider and IFileInfo provides changing the contents of view at compile-time. So, we could replace and provide static data in views with a template engine(i.e. http://dotliquidmarkup.org/).
Check this;
https://www.mikesdotnetting.com/article/301/loading-asp-net-core-mvc-views-from-a-database-or-other-location
I'm practicing web programming by using Spring 3.1, Hibernate and SiteMesh3.
I want to move 'sitemesh3.xml' file to other directory as WEB-INF/spring/ (not in WEB-INF directly). I've tried it, but sitemesh didn't work. Is it possible to move it? If it is, what properties, if any, should I add on other files like web.xml?
(I've read http://wiki.sitemesh.org/wiki/display/sitemesh3/Configuring+SiteMesh+3, which says "The configuration file should live in /WEB-INF/sitemesh3.xml in your web-application.")
Consider using java config, you can get rid of xml configuration totally.
Follow Sitemesh Java Config
Create a filter like this and register it in your web.xml or in java configuration file.
#WebFilter(urlPatterns = "/*")
public class ConfiguredSiteMeshFilter extends ConfigurableSiteMeshFilter {
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
builder.addDecoratorPath("/*", "/WEB-INF/decorators/defaultDecorator.jsp");
}
}
I have an application built with Windsor, this application has features and al the components are manually registered inside xml which also contains their configuration. This is an example:
<component type="type">
<parameters>
[...]
</parameters>
</component>
I decided to refactor my components and separate them into windsor installers, one installer for each feature. My problem now is to decide where to put the configuration of the components registered inside each installer.
Before this decision, the user could find the appropriate configuration of the components mostly inside the parameters element of xml, and I did not have to write wire logic for that to work.
Now I'm a bit confused because it seems like I don't have anymore such automatism. Since I decided to declare the installers of my application by xml, I think it could be perfect if I could put this configuration inside the installr element like this:
<installers>
<install assembly="myassembly">
<parameters>
[...]
<parameters>
</install>
</installers>
I don't know if Windsor supports this syntax. If it does, then I wonder how I could access it from inside the installer and how to wire it up to my components and services.
Another accettable alternative could be to create and register on xml a component containing all the configuration of my feature:
<components>
<component type="featureConfiguration">
<parameters>
</parameters>
</component>
</components>
In this case I guess that I have to refactor my components to let them receive such type as argument in their constructor whereas before I had direct properties, in other words before I could tell exactly what were the dependencies of my components by looking at the code, with this new form I pass to them the whole configuration but I don't know anymore what specific properties of the configuration are used in this or that component.
To use this second solution and to avoid this confusion I should avoid to pass the whole configuration to my subcomponents, and let that single properties do the work, but I have to find a glue between the properties of this configuration component and the properties of the components and services of the installer.
I think that rather than a component I could also put all my configuration inside the properties element of xml:
<properties>
<featureConfiguration>
[property list]
</featureConfiguration>
</properties>
but again, I have to find the glue between each single property in the list and the properties of my components.
Any help is appreciated.
Thank you.
Maybe you will find this mixed solution helpful, depending on the level of the parameterization of your components that you need. Namely, you could perform the component registration in your installers and set the parameters of the components in a windsor config file. This is useful when you have parameterization needs on few of your components while letting Windsor handle all other dependencies.
Example:
Let's say that you have the following components.
public class MyComponent
{
public MyComponent(MyDependency dependency, string stringParameter, DateTime dateParameter)
{
this.Dependency = dependency;
this.StringParameter = stringParameter;
this.DateParameter = dateParameter;
}
public DateTime DateParameter { get; set; }
public string StringParameter { get; set; }
public MyDependency Dependency { get; set; }
}
public class MyDependency
{
}
Then you could use the following installer to register them.
public class MyInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<MyComponent>().Named("MyComponent"));
container.Register(Component.For<MyDependency>());
}
}
Note, that we have been explicit about the unique name of the component, set to MyComponent. But you can use also the default full name.
The windsor config file could look like this:
<configuration>
<components>
<component id="MyComponent">
<parameters>
<stringParameter>Some string</stringParameter>
<dateParameter>2013/09/25</dateParameter>
</parameters>
</component>
</components>
</configuration>
And now you can wrap it all together:
WindsorContainer container = new WindsorContainer();
container.Install(Configuration.FromXmlFile("windsor.config"));
container.Install(FromAssembly.This());
Note that the order of invoking the Install method is important; you must first install the config file settings.
I have a RazorEngine project that fails following an upgrade to Razor 2.0 and RazorEngine 3.2.0
This worked fine in the previous Razor 1.0 based version of RazorEngine (3.0.8).
I have an instance (myInstance) of a class (MyClass) and and extension method:
namespace MyCompany.Extensions
{
public static class MyClassExtensions
{
public static string ExtensionMethod(this MyClass thing)
{
// do stuff
}
}
}
I want to call this in a RazorEngine view (simplified example, there are loads of these methods, and all fail the same way):
#using MyCompany.Extensions
#using MyCompany
#{
var myInstance = new MyClass(Model, ...);
}
Some text #myInstance.ExtensionMethod() some more text
This is in a text file that's compiled by RazorEngine:
string parsedResult = RE::Razor.Parse(fileContent, myModel, "testfile.txt");
The problem is that this line (which used to work) throws a RuntimeBinderException:
'MyCompany.MyClass' does not contain a definition for 'ExtensionMethod'
Note that if I change the text file to:
Some text #MyClassExtensions.ExtensionMethod(myInstance) some more text
It works fine, so I think it must find the extension method's namespace.
My first thought was that it must be considering the passed model as a dynamic (and hence anything derived from it as dynamic too), but it knows the expected type in the RuntimeBinderException. As the exception is run-time I think it must be failing to identify the extension method while the template is compiled, but why would that have changed?
I'm not sure what's changed between 3.0.8 and 3.2.0, or why this is broken. Is there something I need to add so that the extension method can be found while the template is compiled?
This is a bug in RazorEngine: the Razor.Compile works on TemplateBase<dynamic> (so Model and everything derived from it is dynamic too) and that means that no extension methods undergo the 'compiler-magic' to convert them to the static calls. Then Razor.Run passes the Model as the correct type, but the extension method syntax is called as an instance method.
There will probably be a fix for this soon (the bug's only a few days old and this is a corner case), but in the meantime I have a workaround: explicitly type the Model in the Razor template
#using MyCompany.Extensions
#using MyCompany
#{
ExpectedModelClass strongTypeModel = Model as ExpectedModelClass;
MyClass myInstance = new MyClass(strongTypeModel , ...);
}
Some text #myInstance.ExtensionMethod() some more text
This now works, because even though Model is still dynamic at compile-time that doesn't spread to myInstance any more.
It's not ideal, and everywhere I used Model now has to be strongTypeModel, but that's a much simpler substitution.
As we all know, when we derive a class and use polymorphism, someone, somewhere needs to know what class to instanciate. We can use factories, a big switch statement, if-else-if, etc. I just learnt from Bill K this is called Dependency Injection.
My Question: Is it good practice to use reflection and attributes as the dependency injection mechanism? That way, the list gets populated dynamically as we add new types.
Here is an example. Please no comment about how loading images can be done other ways, we know.
Suppose we have the following IImageFileFormat interface:
public interface IImageFileFormat
{
string[] SupportedFormats { get; };
Image Load(string fileName);
void Save(Image image, string fileName);
}
Different classes will implement this interface:
[FileFormat]
public class BmpFileFormat : IImageFileFormat { ... }
[FileFormat]
public class JpegFileFormat : IImageFileFormat { ... }
When a file needs to be loaded or saved, a manager needs to iterate through all known loader and call the Load()/Save() from the appropriate instance depending on their SupportedExtensions.
class ImageLoader
{
public Image Load(string fileName)
{
return FindFormat(fileName).Load(fileName);
}
public void Save(Image image, string fileName)
{
FindFormat(fileName).Save(image, fileName);
}
IImageFileFormat FindFormat(string fileName)
{
string extension = Path.GetExtension(fileName);
return formats.First(f => f.SupportedExtensions.Contains(extension));
}
private List<IImageFileFormat> formats;
}
I guess the important point here is whether the list of available loader (formats) should be populated by hand or using reflection.
By hand:
public ImageLoader()
{
formats = new List<IImageFileFormat>();
formats.Add(new BmpFileFormat());
formats.Add(new JpegFileFormat());
}
By reflection:
public ImageLoader()
{
formats = new List<IImageFileFormat>();
foreach(Type type in Assembly.GetExecutingAssembly().GetTypes())
{
if(type.GetCustomAttributes(typeof(FileFormatAttribute), false).Length > 0)
{
formats.Add(Activator.CreateInstance(type))
}
}
}
I sometimes use the later and it never occured to me that it could be a very bad idea. Yes, adding new classes is easy, but the mechanic registering those same classes is harder to grasp and therefore maintain than a simple coded-by-hand list.
Please discuss.
My personal preference is neither - when there is a mapping of classes to some arbitrary string, a configuration file is the place to do it IMHO. This way, you never need to modify the code - especially if you use a dynamic loading mechanism to add new dynamic libraries.
In general, I always prefer some method that allows me to write code once as much as possible - both your methods require altering already-written/built/deployed code (since your reflection route makes no provision for adding file format loaders in new DLLs).
Edit by Coincoin:
Reflection approach could be effectively combined with configuration files to locate the implmentations to be injected.
The type could be declared explicitely in the config file using canonical names, similar to MSBuild <UsingTask>
The config could locate the assemblies, but then we have to inject all matching types, ala Microsoft Visual Studio Packages.
Any other mechanism to match a value or set of condition to the needed type.
My vote is that the reflection method is nicer. With that method, adding a new file format only modifies one part of the code - the place where you define the class to handle the file format. Without reflection, you'll have to remember to modify the other class, the ImageLoader, as well
Isn't this pretty much what the Dependency Injection pattern is all about?
If you can isolate the dependencies then the mechanics will almost certainly be reflection based, but it will be configuration file driven so the messiness of the reflection can be pretty well encapsulated and isolated.
I believe with DI you simply say I need an object of type <interface> with some other parameters, and the DI system returns an object to you that satisfies your conditions.
This goes together with IoC (Inversion of Control) where the object being supplied may need something else, so that other thing is automatically created and installed into your object (being created by DI) before it's returned to the user.
I know this borders on the "no comment about loading images other ways", but why not just flip your dependencies -- rather than have ImageLoader depend on ImageFileFormats, have each IImageFileFormat depend on an ImageLoader? You'll gain a few things out of this:
Each time you add a new IImageFileFormat, you won't need to make any changes anywhere else (and you won't have to use reflection, either)
If you take it one step further and abstract ImageLoader, you can mock it in Unit Tests, making testing the concrete implementations of each IImageFileFormat that much easier
In vb.net, if all the image loaders will be in the same assembly, one could use partial classes and events to achieve the desired effect (have a class whose purpose is to fire an event when the image loaders should register themselves; each file containing image loaders can have use a "partial class" to add another event handler to that class); C# doesn't have a direct equivalent to vb.net's WithEvents syntax, but I suspect partial classes are a limited mechanism for achieving the same thing.