Version 6.0 got a new feature of nameof, but I can't understand the purpose of it, as it just takes the variable name and changes it to a string on compilation.
I thought it might have some purpose when using <T> but when I try to nameof(T) it just prints me a T instead of the used type.
Any idea on the purpose?
What about cases where you want to reuse the name of a property, for example when throwing exception based on a property name, or handling a PropertyChanged event. There are numerous cases where you would want to have the name of the property.
Take this example:
switch (e.PropertyName)
{
case nameof(SomeProperty):
{ break; }
// opposed to
case "SomeOtherProperty":
{ break; }
}
In the first case, renaming SomeProperty will cause a compilation error if you don't change both the property definition and the nameof(SomeProperty) expression. In the second case, renaming SomeOtherProperty or altering the "SomeOtherProperty" string will result in silently broken runtime behavior, with no error or warning at build time.
This is a very useful way to keep your code compiling and bug free (sort-of).
(A very nice article from Eric Lippert why infoof didn't make it, while nameof did)
It's really useful for ArgumentException and its derivatives:
public string DoSomething(string input)
{
if(input == null)
{
throw new ArgumentNullException(nameof(input));
}
...
Now if someone refactors the name of the input parameter the exception will be kept up to date too.
It is also useful in some places where previously reflection had to be used to get the names of properties or parameters.
In your example nameof(T) gets the name of the type parameter - this can be useful too:
throw new ArgumentException(nameof(T), $"Type {typeof(T)} does not support this method.");
Another use of nameof is for enums - usually if you want the string name of an enum you use .ToString():
enum MyEnum { ... FooBar = 7 ... }
Console.WriteLine(MyEnum.FooBar.ToString());
> "FooBar"
This is actually relatively slow as .Net holds the enum value (i.e. 7) and finds the name at run time.
Instead use nameof:
Console.WriteLine(nameof(MyEnum.FooBar))
> "FooBar"
Now .Net replaces the enum name with a string at compile time.
Yet another use is for things like INotifyPropertyChanged and logging - in both cases you want the name of the member that you're calling to be passed to another method:
// Property with notify of change
public int Foo
{
get { return this.foo; }
set
{
this.foo = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Foo));
}
}
Or...
// Write a log, audit or trace for the method called
void DoSomething(... params ...)
{
Log(nameof(DoSomething), "Message....");
}
Another use-case where nameof feature of C# 6.0 becomes handy - Consider a library like Dapper which makes DB retrievals much easier. Albeit this is a great library, you need to hardcode property/field names within query. What this means is that if you decide to rename your property/field, there are high chances that you will forget to update query to use new field names. With string interpolation and nameof features, code becomes much easier to maintain and typesafe.
From the example given in link
without nameof
var dog = connection.Query<Dog>(
"select Age = #Age, Id = #Id",
new {Age = (int?) null, Id = guid});
with nameof
var dog = connection.Query<Dog>(
$"select {nameof(Dog.Age)} = #Age, {nameof(Dog.Id)} = #Id",
new {Age = (int?) null, Id = guid});
Your question already expresses the purpose. You must see this might be useful for logging or throwing exceptions.
For example:
public void DoStuff(object input)
{
if (input == null)
{
throw new ArgumentNullException(nameof(input));
}
}
This is good. If I change the name of the variable, the code will break instead of returning an exception with an incorrect message.
Of course, the uses are not limited to this simple situation. You can use nameof whenever it would be useful to code the name of a variable or property.
The uses are manifold when you consider various binding and reflection situations. It's an excellent way to bring what were run time errors to compile time.
The most common use case I can think of is when working with the INotifyPropertyChanged interface. (Basically everything related to WPF and bindings uses this interface)
Take a look at this example:
public class Model : INotifyPropertyChanged
{
// From the INotifyPropertyChanged interface
public event PropertyChangedEventHandler PropertyChanged;
private string foo;
public String Foo
{
get { return this.foo; }
set
{
this.foo = value;
// Old code:
PropertyChanged(this, new PropertyChangedEventArgs("Foo"));
// New Code:
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Foo)));
}
}
}
As you can see in the old way we have to pass a string to indicate which property has changed. With nameof we can use the name of the property directly. This might not seem like a big deal. But image what happens when somebody changes the name of the property Foo. When using a string the binding will stop working, but the compiler will not warn you. When using nameof you get a compiler error that there is no property/argument with the name Foo.
Note that some frameworks use some reflection magic to get the name of the property, but now we have nameof this is no longer neccesary.
Most common usage will be in input validation, such as
//Currently
void Foo(string par) {
if (par == null) throw new ArgumentNullException("par");
}
//C# 6 nameof
void Foo(string par) {
if (par == null) throw new ArgumentNullException(nameof(par));
}
In first case, if you refactor the method changing par parameter's name, you'll probably forget to change that in the ArgumentNullException. With nameof you don't have to worry about that.
See also: nameof (C# and Visual Basic Reference)
The ASP.NET Core MVC project uses nameof in the AccountController.cs and ManageController.cs with the RedirectToAction method to reference an action in the controller.
Example:
return RedirectToAction(nameof(HomeController.Index), "Home");
This translates to:
return RedirectToAction("Index", "Home");
and takes takes the user to the 'Index' action in the 'Home' controller, i.e. /Home/Index.
Let's say you need to print the name of a variable in your code. If you write:
int myVar = 10;
print("myVar" + " value is " + myVar.toString());
and then if someone refactors the code and uses another name for myVar, he/she would have to look for the string value in your code and change it accordingly.
Instead, if you write:
print(nameof(myVar) + " value is " + myVar.toString());
It would help to refactor automatically!
The MSDN article lists MVC routing (the example that really clicked the concept for me) among several others. The (formatted) description paragraph reads:
When reporting errors in code,
hooking up model-view-controller (MVC) links,
firing property changed events, etc.,
you often want to
capture the string name of a method. Using nameof helps keep your code
valid when renaming definitions.
Before you had to use string literals
to refer to definitions, which is brittle when renaming code elements
because tools do not know to check these string literals.
The accepted / top rated answers already give several excellent concrete examples.
As others have already pointed out, the nameof operator does insert the name that the element was given in the sourcecode.
I would like to add that this is a really good idea in terms of refactoring since it makes this string refactoring safe. Previously, I used a static method which utilized reflection for the same purpose, but that has a runtime performance impact. The nameof operator has no runtime performance impact; it does its work at compile time. If you take a look at the MSIL code you will find the string embedded. See the following method and its disassembled code.
static void Main(string[] args)
{
Console.WriteLine(nameof(args));
Console.WriteLine("regular text");
}
// striped nops from the listing
IL_0001 ldstr args
IL_0006 call System.Void System.Console::WriteLine(System.String)
IL_000C ldstr regular text
IL_0011 call System.Void System.Console::WriteLine(System.String)
IL_0017 ret
However, that can be a drawback if you plan to obfuscate your software. After obfuscation the embedded string may no longer match the name of the element. Mechanisms that rely on this text will break. Examples for that, including but not limited to are: Reflection, NotifyPropertyChanged ...
Determining the name during runtime costs some performance, but is safe for obfuscation. If obfuscation is neither required nor planned, I would recommend using the nameof operator.
The purpose of the nameof operator is to provide the source name of the artifacts.
Usually the source name is the same name as the metadata name:
public void M(string p)
{
if (p == null)
{
throw new ArgumentNullException(nameof(p));
}
...
}
public int P
{
get
{
return p;
}
set
{
p = value;
NotifyPropertyChanged(nameof(P));
}
}
But this may not always be the case:
using i = System.Int32;
...
Console.WriteLine(nameof(i)); // prints "i"
Or:
public static string Extension<T>(this T t)
{
return nameof(T); returns "T"
}
One use I've been giving to it is for naming resources:
[Display(
ResourceType = typeof(Resources),
Name = nameof(Resources.Title_Name),
ShortName = nameof(Resources.Title_ShortName),
Description = nameof(Resources.Title_Description),
Prompt = nameof(Resources.Title_Prompt))]
The fact is that, in this case, I didn't even need the generated properties to access the resources, but now I have a compile time check that the resources exist.
The purpose of nameof is refactoring. For example when you change the name of a class to which you refer to through nameof somewhere else in your code you will get a compilation error which is what you want. If you didn't use nameof and had just a plain string as a reference you'd have to fulltext search for the name of the class in order to change it. That's a pain in the bottom. With nameof you can rest easy, build, and get all the cases for change automatically in your IDE.
Another use case of nameof is to check tab pages, instead of checking the index you can check the Name property of the tabpages as follow:
if(tabControl.SelectedTab.Name == nameof(tabSettings))
{
// Do something
}
Less messy :)
I find that nameof increases the readability of very long and complex SQL statements in my applications. It makes the variables stand out of that sea of strings and eliminates your job of figuring out where the variables are used in your SQL statements.
public bool IsFooAFoo(string foo, string bar)
{
var aVeryLongAndComplexQuery = $#"SELECT yada, yada
-- long query in here
WHERE fooColumn = #{nameof(foo)}
AND barColumn = #{nameof(bar)}
-- long query here";
SqlParameter[] parameters = {
new SqlParameter(nameof(foo), SqlDBType.VarChar, 10){ Value = foo },
new SqlParameter(nameof(bar), SqlDBType.VarChar, 10){ Value = bar },
}
}
One of the usage of nameof keyword is for setting Binding in wpf programmatically.
to set Binding you have to set Path with string, and with nameof keyword, it's possible to use Refactor option.
For example, if you have IsEnable dependency property in your UserControl and you want to bind it to IsEnable of some CheckBox in your UserControl, you can use these two codes:
CheckBox chk = new CheckBox();
Binding bnd = new Binding ("IsEnable") { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);
and
CheckBox chk = new CheckBox();
Binding bnd = new Binding (nameof (IsEnable)) { Source = this };
chk.SetBinding(IsEnabledProperty, bnd);
It's obvious the first code can't refactor but the secend one...
Previously we were using something like that:
// Some form.
SetFieldReadOnly( () => Entity.UserName );
...
// Base form.
private void SetFieldReadOnly(Expression<Func<object>> property)
{
var propName = GetPropNameFromExpr(property);
SetFieldsReadOnly(propName);
}
private void SetFieldReadOnly(string propertyName)
{
...
}
Reason - compile time safety. No one can silently rename property and break code logic. Now we can use nameof().
It has advantage when you use ASP.Net MVC. When you use HTML helper to build some control in view it uses property names in name attribure of html input:
#Html.TextBoxFor(m => m.CanBeRenamed)
It makes something like that:
<input type="text" name="CanBeRenamed" />
So now, if you need to validate your property in Validate method you can do this:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (IsNotValid(CanBeRenamed)) {
yield return new ValidationResult(
$"Property {nameof(CanBeRenamed)} is not valid",
new [] { $"{nameof(CanBeRenamed)}" })
}
}
In case if you rename you property using refactoring tools, your validation will not be broken.
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
So, it's pretty well known that the infamous NullReferenceException is the most common exception in software products. I've been reading some articles, and found myself with the Optional approach.
Its aim is to create some kind of encapsulation around a nullable value
public sealed class Optional<T> where T : class {
private T value;
private Optional(T value) {
this.value = value;
}
//Used to create an empty container
public static Optional<T> Empty() {
return new Optional(null);
}
//Used to create a container with a non-null value
public static Optional<T> For(T value) {
return new Optional(value);
}
//Used to check if the container holds a non-null value
public bool IsPresent {
get { return value != null; }
}
//Retrieves the non-null value
public T Value {
get { return value; }
}
}
Afterwards, the now optional value can be returned like this:
public Optional<ICustomer> FindCustomerByName(string name)
{
ICustomer customer = null;
// Code to find the customer in database
if(customer != null) {
return Optional.Of(customer);
} else {
return Optional.Empty();
}
}
And handled like this:
Optional<ICustomer> optionalCustomer = repository.FindCustomerByName("Matt");
if(optionalCustomer.IsPresent) {
ICustomer foundCustomer = optionalCustomer.Value;
Console.WriteLine("Customer found: " + customer.ToString());
} else {
Console.WriteLine("Customer not found");
}
I don't see any improvement, just shifted complexity.
The programmer must remember to check if a value IsPresent, in the same way he must remember to check if a value != null.
And if he forgets, he would get a NullReferenceException on both approaches.
What am I missing? What advantages (if any) does the Optional pattern provide over something like Nullable<T> and the null coalescing operator?
Free your mind
If you think of Option as Nullable by a different name then you are absolutely correct - Option is simply Nullable for reference types.
The Option pattern makes more sense if you view it as a monad or as a specialized collection that contain either one or zero values.
Option as a collection
Consider a simple foreach loop with a list that cannot be null:
public void DoWork<T>(List<T> someList) {
foreach (var el in someList) {
Console.WriteLine(el);
}
}
If you pass an empty list to DoWork, nothing happens:
DoWork(new List<int>());
If you pass a list with one or more elements in it, work happens:
DoWork(new List<int>(1));
// 1
Let's alias the empty list to None and the list with one entry in it to Some:
var None = new List<int>();
var Some = new List(1);
We can pass these variables to DoWork and we get the same behavior as before:
DoWork(None);
DoWork(Some);
// 1
Of course, we can also use LINQ extension methods:
Some.Where(x => x > 0).Select(x => x * 2);
// List(2)
// Some -> Transform Function(s) -> another Some
None.Where(x => x > 0).Select(x => x * 2);
// List()
// None -> None
Some.Where(x => x > 100).Select(x => x * 2);
// List() aka None
// Some -> A Transform that eliminates the element -> None
Interesting side note: LINQ is monadic.
Wait, what just happened?
By wrapping the value that we want inside a list we were suddenly able to only apply an operation to the value if we actually had a value in the first place!
Extending Optional
With that consideration in mind, let's add a few methods to Optional to let us work with it as if it were a collection (alternately, we could make it a specialized version of IEnumerable that only allows one entry):
// map makes it easy to work with pure functions
public Optional<TOut> Map<TIn, TOut>(Func<TIn, TOut> f) where TIn : T {
return IsPresent ? Optional.For(f(value)) : Empty();
}
// foreach is for side-effects
public Optional<T> Foreach(Action<T> f) {
if (IsPresent) f(value);
return this;
}
// getOrElse for defaults
public T GetOrElse(Func<T> f) {
return IsPresent ? value : f();
}
public T GetOrElse(T defaultValue) { return IsPresent ? value: defaultValue; }
// orElse for taking actions when dealing with `None`
public void OrElse(Action<T> f) { if (!IsPresent) f(); }
Then your code becomes:
Optional<ICustomer> optionalCustomer = repository.FindCustomerByName("Matt");
optionalCustomer
.Foreach(customer =>
Console.WriteLine("Customer found: " + customer.ToString()))
.OrElse(() => Console.WriteLine("Customer not found"));
Not much savings there, right? And two more anonymous functions - so why would we do this? Because, just like LINQ, it enables us to set up a chain of behavior that only executes as long as we have the input that we need. For example:
optionalCustomer
.Map(predictCustomerBehavior)
.Map(chooseIncentiveBasedOnPredictedBehavior)
.Foreach(scheduleIncentiveMessage);
Each of these actions (predictCustomerBehavior, chooseIncentiveBasedOnPredictedBehavior, scheduleIncentiveMessage) is expensive - but they will only happen if we have a customer to begin with!
It gets better though - after some study we realize that we cannot always predict customer behavior. So we change the signature of predictCustomerBehavior to return an Optional<CustomerBehaviorPrediction> and change our second Map call in the chain to FlatMap:
optionalCustomer
.FlatMap(predictCustomerBehavior)
.Map(chooseIncentiveBasedOnPredictedBehavior)
.Foreach(scheduleIncentiveMessage);
which is defined as:
public Optional<TOut> FlatMap<TIn, TOut>(Func<TIn, Optional<TOut>> f) where TIn : T {
var Optional<Optional<TOut>> result = Map(f)
return result.IsPresent ? result.value : Empty();
}
This starts to look a lot like LINQ (FlatMap -> Flatten, for example).
Further possible refinements
In order to get more utility out of Optional we should really make it implement IEnumerable. Additionally, we can take advantage of polymorphism and create two sub-types of Optional, Some and None to represent the full list and the empty list case. Then our methods can drop the IsPresent checks, making them easier to read.
TL;DR
The advantages of LINQ for expensive operations are obvious:
someList
.Where(cheapOp1)
.SkipWhile(cheapOp2)
.GroupBy(expensiveOp)
.Select(expensiveProjection);
Optional, when viewed as a collection of one or zero values provides a similar benefit (and there's no reason it couldn't implement IEnumerable so that LINQ methods would work on it as well):
someOptional
.FlatMap(expensiveOp1)
.Filter(expensiveOp2)
.GetOrElse(generateDefaultValue);
Further suggested reading
Option (F#)
When null is not enough (C#)
The neophytes guide to Scala Part 5: The Option type
The Marvel of Monads (C#)
Eric Lippert's series on LINQ and monads
it would probally make more sense if you used something like this
interface ICustomer {
String name { get; }
}
public class OptionalCustomer : ICustomer {
public OptionalCustomer (ICustomer value) {
this.value = value;
}
public static OptionalCustomer Empty() {
return new OptionalCustomer(null);
}
ICustomer value;
public String name { get {
if (value == null ) {
return "No customer found";
}
return value.Name;
}
}
}
now if your pass an "empty" optional customer object you can still call the .Name property (without getting nullpointers)
The advantage of Optional is you know if something may not exist.
The problem with many types of queries that return a null is that that could mean 2 things:
The query didn't return a result
The query returned a result whose value was null.
I know you're asking specifically about C# but Java just introduced Optionals in Java 8 so there are a lot of articles about it so I'll use Java as an example. but it's completely the same idea as in C#:
Consider the Java Map.get(key) method
Object value = map.get(key);
if(value ==null){
//is there an entry in the map key =>null or does key not exist?
}
to get around that you have to have an additional method containsKey( k)
With optional, you only need one method
Optional<Object> result = map.get(key);
if(result.isPresent()){
Object value = result.get();
//if value is null, then we know that key =>null
}
More info see this Java article : http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Did you mean: Null Object pattern
The article linked to me in the comments contains a conclusion section explained this programming tool.
... The purpose of Optional is not to replace every single null reference in your codebase but rather to help design better APIs in which—just by reading the signature of a method—users can tell whether to expect an optional value. .... deal with the absence of a value; as a result, you protect your code against unintended null pointer exceptions.
Anyway, let it crash and find the reason. If you do not want endlessly embedded if statements than use an implementation pattern Guard Clause pattern, which says the following:
While programs have a main flow, some situations require deviations from the
main flow. The guard clause is a way to express simple and local exceptional
situations with purely local consequences.
Let say I have this kind of class in c# language:
public class ABC {
public int var_1;
public int var_2;
public int var_3;
//... until 100
public int var_100;
public int GetData_WithBasicIfElse (int id) {
if(id == 1)
return var_1;
else if(id == 2)
return var_2;
else //and so on until
else if(id == 100)
return var_100;
}
public int GetData_WithReflection(int id){
string key = "var_" + id.ToString ();
FieldInfo info = GetType ().GetField (key);
return info != null ? (int)info.GetValue (this) : 0;
}
public int GetData_WithSpecialCode(int id){
//put the simple codes here, then compilers compile it, it will generate code like the method GetData_WithBasicIfElse
}
}
Actually in most cases, I can use the array to hold var_n variable, but I am just curious if there is another way. I do not want to use GetData_WithBasicIfElse (not elegant), but I am wondering if there is another solution beside using reflection.
What I mean with GetData_WithSpecialCode is, it contains the special code that will be transformed by compiler (when compile time, where it will be binary file) into some pattern like GetData_WithBasicIfElse.
UPDATED
This technique's called Template metaprogramming, as you can see in here: http://en.wikipedia.org/wiki/Template_metaprogramming, in the factorial source code.
T4 Template
A T4 Template can generate that desired C# code, that will be later compiled into IL code, as if you have written that code yourself. If you want to use this technique, the most natural way is to use partial classes. The first partial defines all the class except the auto-generated method. The second partial would be generated by a simple T4 template. (In the compiled code there's no difference between a class defined in a single file or in several partials).
Reflection.Emit
If you really want to generate code at runtime, it's much harder to do, but you can do it using Reflection.Emit This allow to directly emit IL at run time.
Expression Trees
This also allows to generate and compile code at run time. It's easier than the second option. See an introudction here.
Reflection
If you want to use your original Reflection solution you should store the FieldInfos in an static structure (array, list, dictionary or whatever) so that you only have the overhead of reflecting the fields once. This will improve the performace.
What to choose
Unless there is a good reason not to do so, I'd prefer the T4 template. It's the easier to implement, and you leave the compiler the reponsibility to compile and optimize your code. besides you don't have to work with "obscure, unusual" concepts.
In general I wouldn't advice you the second option. Between other things, I think this requires full trust. And, you need a good knowledge of what you're doing. You also miss the compiler optimizations.
Using expression trees is not as hard as using Reflection.Emit, but it's still hard to do.
And reflection always add a little overhead, specially if you don't cache the FieldInfos (or PropertyInfos or whatever). I would leave it for cases where is the only solution. For example checking if a property exists or accessing a private or protected member of a class from ouside.
I really wonder why you can't use array. For sure using some kind of dictionary would be better. But believing you really can't, you have at least two options to generate such a method:
1) CSharpCodeProvider
You can build a string with helper class containing your method, and it will be compiled to a different assembly:
string source = "public class Description" +
"{" +
" public int GetData_WithBasicIfElse(int id) {" +
// ... all ifs generated here
" }" +
"}";
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
System.CodeDom.Compiler.CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = false;
parameters.GenerateInMemory = true;
CompilerResults result = codeProvider.CompileAssemblyFromSource(parameters, source);
if (!result.Errors.HasErrors)
{
Type type = result.CompiledAssembly.GetType("Description");
var instance = Activator.CreateInstance(type);
}
and now you have an instance of helper class
2) Linq Expressions
You can build a method using Linq Expressions
ParameterExpression id = Expression.Parameter(typeof(int), "id");
List<Expression> expressions = new List<Expression>();
// here a lot of adding if-else statement expressions
expressions.Add(...);
var lambda = Expression.Lambda(
Expression.Block(
expressions
),
id);
Then you can use a result of lambda.Compile() as a method to call dynamically.
You can use a dictionary to map the ids:
public class ABC
{
public int var_1;
public int var_2;
public int var_3;
//... until 100
public int var_100;
private Dictionary<int,int> map;
public ABC()
{
//build up the mapping
map = new Dictionary<int,int>();
map.Add(1,var_1);
map.Add(2,var_2);
map.Add(100,var_100);
}
public int GetData(int id)
{
//maybe here you need to do check if the key is present
return map[id];
}
}
Can you change some details in your code? If you define the integers as one Array with 100 elements you can simply use id as an index and return that:
public int GetData_WithSpecialCode(int id){
return var_array(id)
}
If you really need to access the values from outside (they are defined public?) you can expose them using a property wich is preferred to public integers.
I haven't used them, but I know Visual Studio comes with T4 Text Templates that may do what you need.
Of course,
switch (id)
{
case 1:
return this.var_1;
case 2:
return this.var_2;
// etc. etc.
}
or,
var lookup = new Dictionary<int, Func<int>>
{
{ 1, () => return this.var_1 },
{ 2, () => return this.var_2 },
// etc. etc.
};
return lookup[i]();
I have been using moles to write unit tests on the hard to reach parts of my code – particularly where I use the types found in the sitecore class libraries (which are hard to use mocking frameworks with). I have come across a surprisingly tricky problem where I’m trying to mole a LinkField type and test the following kind of code snippet.
LinkField linkField = item.Fields["External Url"];
if (linkField.IsInternal && linkField.TargetItem != null)
{
// want to test this path
item.Fields is a field collection whose indexer returns a type of SiteCore.Data.Field, but LinkField is set up such that uses an implicit operator which hides the conversion which means you are able to work with an instance of LinkField in your code.
My difficulty is that I cannot create a mole of type MLinkField, and assign this to the FieldCollection in the Item as it is strongly typed to Field. Moreover, it seems that whilst I am able to create a type of MField, when the implicit conversion happens, it will work and return an object but none of the fields are set to have any values. This means, I can’t test the code path above which relies on the state of the linkField being set a certain way.
The only way I can think of setting these values is indirectly – i.e. finding what values need to be set by analysing the implicit conversion and setting these in MField. The implicit operator calls the LinkField constructor as follows:
public LinkField(Field innerField) : base(innerField, "link")
which means I need to be conscious of how it instantiates the base type (XmlField), and in turn that class’s base type (CustomField).
Then, to look at what underlying values TargetItem is looking for. The end result is the need to mole out:
InnerField.Database.Items[internalPath];
Or
InnerField.Database.Items[targetID];
Where InnerField is effectively my MField.
Does anyone have a better idea? This sounds horribly convoluted but I think that’s the nature of the beast with these assemblies.
It can be done but you'll need to jump through a few hoops to make it work.
First of all, a bit of background:
LinkField does not inherit from the Field class like some other field types do.
LinkField inherits from XmlField which in turn inherits from CustomField.
CustomField (and it's subtypes) are instantiated by passing a field instance into the constructor.
Linkfields store their values in this field instance.
Linkfields cannot be added to a FieldCollection as they do not inherit from Field.
Rather than add the LinkField we need to add the LinkField's InnerField property.
When a Field is pulled from a FieldCollection and assigned to a LinkField an implicit conversion operation is performed.
The implicit conversion operation creates a new LinkField by passing the selected field to the LinkField's constructor. It is this new LinkField that is returned.
Now some code:
const string externalUrl = "External Url";
const string targetItemName = "Target Item";
Field field = new ShimField { IDGet = () => ID.NewID, NameGet = () => externalUrl };
Item targetitem = new ShimItem { IDGet = () => ID.NewID, NameGet = () => targetItemName };
LinkField linkfield = new ShimLinkField(field) { IsInternalGet = () => true, TargetItemGet = () => targetitem };
ShimLinkField.ImplicitOpFieldLinkField = (f) => linkfield;
FieldCollection fields = new ShimFieldCollection { ItemGetString = (name) => linkfield.InnerField };
Item item = new ShimItem { NameGet = () => "Test Item", FieldsGet = () => fields };
And now for a bit of explanation:
The key to making the above code work is the line:
ShimLinkField.ImplicitOpFieldLinkField = (f) => linkfield;
By Shimming the implicit conversion operator, we can ensure that when the following line is called:
LinkField linkField = item.Fields["External Url"];
A link field is returned and it's properties are shimmed as you want them.
Since LinkField cannot be mocked in a proper way it have to be used in unit tests "as is" meaning that you'll have to test both your code and the link field implementation.
The good news is that the Link field is an XmlField that operates with the xml data stored in the inner field value. In order to configure the link field behavior you just need to set proper xml in the value.
With Sitecore.FakeDb you can easily create content in memory and configure items and fields you need. The following code creates items home and target. The home item has got Url link field which has TargetId pointed to the target item:
ID targetId = ID.NewID;
using (var db = new Db
{
new DbItem("home")
{
// Field 'Url' is an internal link which targets the 'target' item
{ "Url", "<link linktype=\"internal\" id=\"{0}\" />".FormatWith(targetId) }
},
new DbItem("target", targetId)
})
{
Item item = db.GetItem("/sitecore/content/home");
LinkField linkField = item.Fields["Url"];
linkField.IsInternal.Should().BeTrue();
linkField.TargetItem.Should().NotBeNull();
linkField.TargetItem.Paths.FullPath.Should().Be("/sitecore/content/target");
}
Personally speaking, I do try to abstract Sitecore away from business logic that doesn't need to interact with it directly; however I'm mindful that some things will need to deal with it directly and I try not to take it too far. If you spend too much time abstracting Sitecore out of your logic, then in my opinion you can end up making it more difficult to take advantage of some features that make Sitecore useful.
While unit testing purists may disagree with my approach, I will have unit tests that use the Sitecore API to properly instantiate items. Doing so is fairly straight-forward, I wrote a blog post about it a while ago. Then your only problem is dealing with test data, but it's fairly easy to create it with a test set-up and remove it with a test tear-down.
I want to match (select from class file) methodsname, properties name and fields name.
This is example class:
class Perl
{
string _name;
public string Name { get; set; }
public Perl()
{
// Assign this._name
this._name = "Perl";
// Assign _name
_name = "Sam";
// The two forms reference the same field.
Console.WriteLine(this._name);
Console.WriteLine(_name);
}
public static string doSomething(string test)
{
bla test;
}
}
I got code for the methods:
(?:public|private|protected)([\s\w]*)\s+(\w+)\s*\(\s*(?:\w+\s+(\w+)\s*,?\s*)+\)
And i got questions:
this above regex code gets all methods and it works pretty well but
also i want it to select method name but without parameters and
accessors. So from exaplmce class using my code result will be:
public Perl() and public static doSomething(string test) but i want that kind of result: Perl() and doSomething(). So -
my code matches good but i want result to be displayed just like I
wrote in previous sentence.
how to select properties ? with result displayed: type and property
name. So from exaple class result will be: string Name
how to select fields with result: type field_name. In out case it
will be: string _name
Use this Regex
for methods
(?:public\s|private\s|protected\s|internal\s)?[\s\w]*\s+(?<methodName>\w+)\s*\(\s*(?:(ref\s|/in\s|out\s)?\s*(?<parameterType>\w+)\s+(?<parameter>\w+)\s*,?\s*)+\)
and get groups named methodName and parameterType and parameter.
and for fields:
(?:public\s|private\s|protected\s)\s*(?:readonly\s+)?(?<type>\w+)\s+(?<name>\w+)
and get groups named type and name.
for example your code for methods can be like this:
var inputString0 = "public void test(string name, out int value)\r\nvoid test(string name, int value)";
foreach (Match match in Regex.Matches(inputString0, #"(?:public\s|private\s|protected\s)?[\s\w]*\s+(?<methodName>\w+)\s*\(\s*(?:(ref\s|/in\s|out\s)?\s*(?<parameterType>[\w\?\[\]]+)\s+(?<parameter>\w+)\s*,?\s*)+\)"))
{
var methodName = match.Groups["methodName"].Value;
var typeParameterPair = new Dictionary<string, string>();
int i = 0;
foreach (var capture in match.Groups["parameterType"].Captures)
{
typeParameterPair.Add(match.Groups["parameterType"].Captures[i].Value, match.Groups["parameter"].Captures[i].Value);
i++;
}
}
You can use Irony - .NET Language Implementation Kit from codeplex too.
As stated in comments to your answer, much more reliable method is to compile your .cs files and then use reflection to interrogate types for members you are interested in. It will involve the following:
Use C# compiler (csc.exe) to compile your files. MSDN contains helpful examples and hints. You could do this manually, or, if you want to automatize the whole thing, you could execute csc.exe programmatically with Process class.
Use Assembly.LoadFile() method to load the resulting assembly.
You can now employ reflection to get types from the assembly and interrogate them.
EDIT: As an alternative to csc.exe, you could use CodeDOM - there is an example that contains all you need.
A language such as C# accepts too many variations in statements syntax to be parsed using regular expressions only. On top of regexes, you need a contextual grammar parser.
I would give Roslyn a try: It's a C# compiler whose internals are accessible from your code. Ask Roslyn to parse the code and query it about whatever info you need.
I suggest looking at Microsoft.VisualStudio.CSharp.Services.Language namespace and other Visual Studio Extensibility functionality. This would eliminate the need to compile.
In my business layer, I need many, many methods that follow the pattern:
public BusinessClass PropertyName
{
get
{
if (this.m_LocallyCachedValue == null)
{
if (this.Record == null)
{
this.m_LocallyCachedValue = new BusinessClass(
this.Database, this.PropertyId);
}
else
{
this.m_LocallyCachedValue = new BusinessClass(
this.Database, this.Record.ForeignKeyName);
}
}
return this.m_LocallyCachedValue;
}
}
I am still learning C#, and I'm trying to figure out the best way to write this pattern once and add methods to each business layer class that follow this pattern with the proper types and variable names substituted.
BusinessClass is a typename that must be substituted, and PropertyName, PropertyId, ForeignKeyName, and m_LocallyCachedValue are all variables that should be substituted for.
Are attributes usable here? Do I need reflection? How do I write the skeleton I provided in one place and then just write a line or two containing the substitution parameters and get the pattern to propagate itself?
EDIT: Modified my misleading title -- I am hoping to find a solution that doesn't involve code generation or copy/paste techniques, and rather to be able to write the skeleton of the code once in a base class in some form and have it be "instantiated" into lots of subclasses as the accessor for various properties.
EDIT: Here is my solution, as suggested but left unimplemented by the chosen answerer.
// I'll write many of these...
public BusinessClass PropertyName
{
get
{
return GetSingleRelation(ref this.m_LocallyCachedValue,
this.PropertyId, "ForeignKeyName");
}
}
// That all call this.
public TBusinessClass GetSingleRelation<TBusinessClass>(
ref TBusinessClass cachedField, int fieldId, string contextFieldName)
{
if (cachedField == null)
{
if (this.Record == null)
{
ConstructorInfo ci = typeof(TBusinessClass).GetConstructor(
new Type[] { this.Database.GetType(), typeof(int) });
cachedField = (TBusinessClass)ci.Invoke(
new object[] { this.Database, fieldId });
}
else
{
var obj = this.Record.GetType().GetProperty(objName).GetValue(
this.Record, null);
ConstructorInfo ci = typeof(TBusinessClass).GetConstructor(
new Type[] { this.Database.GetType(), obj.GetType()});
cachedField = (TBusinessClass)ci.Invoke(
new object[] { this.Database, obj });
}
}
return cachedField;
}
Check out CodeSmith. They have a free trial and it's not too expensive if you want to purchase it. I've used it and it's great for generating code based on databases (which is what I'm guessing you're doing). Once you have your template setup, you can regenerate the code at any time. You can have it read the property names right from the database schema or you can enter the values you want to use. I'm sure you could even get it to read the values from a file if you wanted to generate a whole batch of classes at once.
You could check out using T4 Templates. I am not quite sure which is "the" resource for T4, but I found a good article on it in VisualStudioMagazine.
It is free, has an easy to use syntax and is actually used by a lot of projects (e.g. Subsonic) for code generation, so you should be able to find some real-world scenarios.
You can code-gen using CodeSmith or MyGeneration or the like. You'd probably store a list of classes and properties somewhere and then pass that data to the code generator. You may want to investigate using pre-build events to re-gen those classes prior to compiling the solution.
Or, you could bake this functionality into a base class or helper method.
public BusinessClass MyProperty
{
get { return GetCached("MyProperty", "PropertyId", "FKName", "LocalValue"); }
}
I'll leave the body of GetCached() up to you, but it's basically the same as what you posted with the variables passed in as arguments.
If any of those values are the same for all properties in a class then you could of course pull them from instance variables, and only pass to GetCached() those things that vary on a per-property basis.
Bottom line: if there's a way to abstract the logic of what you're doing into a base method, so that using that logic becomes a one-liner, then that's probably the best way to go because it's easier to override when you have special cases. If you can't do that, code generation can do the grunt work for you, but you'll need to work out things like when do I re-gen, how do I regen, etc.