Afterthought seems not working, simple code - c#

I wrote simple piece of code to get involved into Afterthought, but it doesn't work and I've got no idea why. A huge part of it is taken from other SO question: How to implement simple Property Ammendment with Afterthought.
using System;
using System.Collections.Generic;
using Afterthought;
namespace SecondAmendmentTest
{
class Program
{
public class TestUser
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool HasChanged { get; set; }
public void method()
{
Console.WriteLine("method");
}
}
public class TestUserAmmendment<T> : Amendment<T, T> where T : TestUser
{
public TestUserAmmendment()
{
Properties
.AfterSet((instance, x, y, z, a) => instance.HasChanged = true);
Methods.After(ExceptionMethod);
}
private object ExceptionMethod(T instance, string method, object[] parameters, object result)
{
throw new NotImplementedException();
}
}
static void Main(string[] args)
{
TestUser tu = new TestUser();
Console.WriteLine("Has changed: " + tu.HasChanged.ToString());
Console.WriteLine("Performing changes...");
tu.Id = 5;
tu.FirstName = "name";
tu.LastName = "lastname";
Console.WriteLine("Has changed: " + tu.HasChanged.ToString());
tu.method();
Console.ReadKey();
}
}
}
It compiles, but no changes are made into output exe file. I've configured post build event. Build output:
1>------ Rebuild All started: Project: SecondAmendmentTest, Configuration: Debug Any CPU ------
1> SecondAmendmentTest -> C:\Users\Lukasz\Documents\Visual Studio 11\Projects\SecondAmendmentTest\SecondAmendmentTest\bin\Debug\SecondAmendmentTest.exe
1> Amending SecondAmendmentTest.exe (5,559 seconds)
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========
And finally output from application after running:
C:\Users\Lukasz\Documents\Visual Studio 11\Projects\SecondAmendmentTest\SecondAmendmentTest\bin\Debug>SecondAmendmentTest.exe
Has changed: False
Performing changes...
Has changed: False
method
Neither HasChanged property were modified nor NotImplementedException was thrown. I'm using last sources from Git. Have you some ideas why it doesn't work?
EDIT: Here is entire solution: SecondAmendmentTest.zip

I know it's a year later but:
To build on Willem van Ketwich's answer, there was actually a bug (oversight?) in Afterthought.NET that wasn't allowing nested types to be amended if thier parent type wasn't amended.
I've submitted a pull request fixing the bug.
In addition to this fix, you still need the [Amendment(typeof(TestUserAmmendment<>))] on your nested class to trigger the amendment.

I got this to work by doing two things:
Move the TestUser and TestUserAmmendment classes out of the Program
class so they aren't nested.
Add the attribute [Amendment(typeof(TestUserAmmendment<>))] to the
TestUser class.
The working solution can be found here.

Related

Visual studio for Mac looks into different class than referenced

After accidentally hitting rename of my skv_match class to skv_player class I have issue with my ReadMatches method. The Visual studio keeps telling me, there is no definition of methods in class skv_player when I use class skv_match instead (after I renamed the class back to skv_match).
I am desperate and don't know if I am doing something wrong or Visual studio for Mac is. Does anybody know how to solve this or did I miss something in the code?
I tried to restart the app and laptop, rebuild and clean project. I also tried deleting the figuring classes, creating them again and pasting the original content in them.
public string ReadMatches()
{
var matches = _context.skv_match.AsNoTracking();
StringBuilder sb = new StringBuilder();
if (matches == null)
{
return "No matches found";
}
else
{
foreach (var skv_match in matches)
{
sb.Append($"Match id: {skv_match.id }\r\n");
sb.Append($"Match results: {skv_match.home_team}");
sb.Append($"{skv_match.home_score }:");
sb.Append($"{skv_match.visitor_score } ");
sb.Append($" {skv_match.visitor_team }\r\n");
}
}
return sb.ToString();
}
public class skv_match
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)]
public int id { get; set; }
public string home_team { get; set; }
public string visitor_team { get; set; }
public int home_score { get; set; }
public int visitor_score { get; set; }
}
I get error: "'skv_player' does not contain a definition for 'home_team' and no accessible extension method 'home_team' accepting a first argument of type 'skv_player' could be found (are you missing a using directive or an assembly reference?)" and same for other methods
I expect the app to just take this without any errors, yet I get error that class I am not referencing misses methods. Before I accidentally hit rename the class everything worked just fine.
Ok my apologies to everyone who took time trying to help me. There was issue in Entity framework DbContext. I don't know if I was just tiredly stupid, or mentioned missclick changed it.
For anyone trying to solve this issue, try Right click on the declaration and "Go to declaration". It will point you to the part where you define it.
To be specific, I clicked on part skv_match at var matches = _context.skv_match.AsNoTracking();

Should I use Multiple RegularExpression attributes

Update 8:
The question has a new title ,hopefully it will help other avoid time consuming bugs...
I have the following code:
(You need a reference to System.ComponentModel.DataAnnotations)
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var itemModelX = new MyModel() { Name = "1<d" };
var contextX = new ValidationContext(itemModelX, serviceProvider: null, items: null);
var resultsX = new List<ValidationResult>();
var isValidX = Validator.TryValidateObject(itemModelX, contextX, resultsX, true);
if (isValidX)
Console.WriteLine("Should not see this");
Console.WriteLine("Finished");
Console.ReadLine();
}
}
public class MyModel
{
[MultipleRegExAttribute2(#"[^?.]{1,100}$")]
[MultipleRegExAttribute2(#"^((?![><&])[\s\S])*$")]
public string Name { get; set; }
}
[System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = true)]
public class MultipleRegExAttribute2 : RegularExpressionAttribute
{
public MultipleRegExAttribute2(string pattern) : base(pattern) { }
}
}
In Visual Studio 2013 Premium Update 5 the output is
"Should not see this"
"Finished"
In Visual Studio 2015 Enterprise Update 1 the output is
"Finished"
Roslyn is the correct one,the question is why 2013 is not working?
I'm pretty sure is that was working in 2013 also,don't know when it broke,I don't have a previous update to test it...
I'm using .NET 4.5.1
Update 1
Even if I remove the reference to System.ComponentModel.DataAnnotations and add the code to my project (You can find the code here) I get different outputs.
Update 2
Forgot to say that it only happens if I have 2 MultipleRegExAttributes ,if I remove the first one it works as expected
Update 3
I've uploaded an entire solution here
Update 4
I check the generated IL for both assemblies but the only difference I see is the initialization of a few locals
VS2015
.locals init (
[0] class [System.ComponentModel.DataAnnotations]System.ComponentModel.DataAnnotations.ValidationContext contextX,
[1] class [mscorlib]System.Collections.Generic.List`1<class [System.ComponentModel.DataAnnotations]System.ComponentModel.DataAnnotations.ValidationResult> resultsX )
VS2013
.locals init (
[0] class ConsoleApp.MyModel itemModelX,
[1] class [System.ComponentModel.DataAnnotations]System.ComponentModel.DataAnnotations.ValidationContext contextX,
[2] class [mscorlib]System.Collections.Generic.List`1<class [System.ComponentModel.DataAnnotations]System.ComponentModel.DataAnnotations.ValidationResult> resultsX,
[3] bool isValidX,
[4] class ConsoleApp.MyModel '<>g__initLocal0'
)
Update 5
Almost there...
VS2015 only checks the second attribute(Which happens to be the one I
care about in the case)
VS2013 only checks the first argument...
Update 6
After many many hours...
- It seems there always is a problem if I have more than 1 RegularExpressionAttribute
That could be my mistake because I extend the class and "override" AllowMultiple
2.Why do I get different results when I compile it with VS2015?
The class that returns the attributes is System.ComponentModel.TypeDescriptor in method GetAttributes.
I have to see what is change there...
Update 7
It seems that something has change in way PropertyDescriptor/MemberDescriptor returns the Attributes.
In VS2015 it prints the second regex,in VS2013 the first.
So,which of the following is true?
a)This is an implementation detail and I shouldn't rely on this
b)This is a bug since it is a breaking change
c)a and b
d)other
.
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var property = TypeDescriptor.GetProperties(typeof(MyModel))[0];
var attribute = property.Attributes.Cast<Attribute>();
foreach (var item in attribute)
if (item is MultipleRegExAttribute2)
Console.WriteLine(((MultipleRegExAttribute2)item).GetPattern());
Console.ReadLine();
}
}
public class MyModel
{
[MultipleRegExAttribute2(#"[^?.]{1,100}$")]
[MultipleRegExAttribute2(#"^((?![><&])[\s\S])*$")]
public string Name { get; set; }
}
[System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = true)]
public class MultipleRegExAttribute2 : RegularExpressionAttribute
{
public MultipleRegExAttribute2(string pattern) : base(pattern) { }
public string GetPattern() { return this.Pattern; }
}
}
DO NOT extend RegularExpressionAttribute and set AllowMultiple to true
It will bring you nothing but trouble.
You can create 2 distinct attributes that inherit from RegularExpressionAttribute.
public class MyModel
{
[MultipleRegExAttribute2(#"[^?.]{1,100}$")]
[MultipleRegExAttribute3(#"^((?![><&])[\s\S])*$")]
public string Name { get; set; }
}
public class MultipleRegExAttribute2 : RegularExpressionAttribute
{
public MultipleRegExAttribute2(string pattern) : base(pattern) { }
}
public class MultipleRegExAttribute3 : RegularExpressionAttribute
{
public MultipleRegExAttribute3(string pattern) : base(pattern) { }
}
Update
A friend of mine showed me the root of the problem.
I have to override the TypeId property.
See this question:Custom validation attribute with multiple instances problem
and this article :The Importance of TypeId in ASP.NET MVC DataAnnotations Validation Attributes

Peculiar Issue When Using Expressions and (Web) Console Application

I ran into an issue the other day that I first believed to be an issue with Entity Framework. I posted a question about it the other day here. Since then, I have determined that this issue is not related to Entity Framework.
Consider the following classes:
public abstract class ModelBase
{
public Guid Id { get; set; }
}
public class User : ModelBase
{
public string Username { get; set; }
}
public abstract class ModelBaseConfiguration<T> where T : ModelBase
{
public virtual void Configure()
{
ConfigureGuidProperty(e => e.Id);
}
protected void ConfigureGuidProperty(Expression<Func<T, Guid>> expression)
{
Debug.WriteLine(expression);
}
protected void ConfigureStringProperty(Expression<Func<T, string>> expression)
{
Debug.WriteLine(expression);
}
}
public class UserConfiguration : ModelBaseConfiguration<User>
{
public override void Configure()
{
base.Configure();
ConfigureStringProperty(e => e.Username);
}
}
If I add the following code to the Main method of an old Console Application project (the one located under the Windows node in VS2015):
UserConfiguration configuration = null;
configuration = new UserConfiguration();
configuration.Configure();
...and execute it, I get the following output in the debug window:
e => e.Id
e => e.Username
This is what I expect.
Now, if I use the exact same code as listed above in a new ConsoleApplication project (the one located under the Web node in VS2015) and execute it, I get the following output in the debug window:
e => Convert(e).Id
e => e.Username
As you can see, the first line of output is different than before. This is what is causing issues with Entity Framework.
I have discovered that the difference is the project type, being that the code is exactly the same in both scenarios. What I am trying to figure out is why. Why is there an attempted conversion in the expression of the second scenario? Is there something I have been missing for some time now? Is this an issue with the new project type? I am trying to educate myself so that I can adjust if necessary.
This issue is corrected after installing the ASP.NET 5 RC1 update.

Enum cannot work when reference it cross multi visual studio solution

I have three solution A, B and C.
I have an enum in A like this:
using System.Runtime.Serialization;
namespace A.Entities
{
[DataContract]
public enum Status
{
[DataMember]
Active = 0,
[DataMember]
Inactive = 1,
}
}
I reference it in solution B like this:
using A.Entities;
namespace B.Entities
{
public class User
{
[DataMember]
public string UserName { get; set; }
[DataMember]
public Status Status { get; set; }
}
}
In solution C, I use them like this:
using B.Entities;
using Status = A.Entities.Status;
namespace C.TestDatas
{
public class UserTestData
{
public static User CreateUser()
{
return new User
{
Status = Status.Active,
}
};
}
}
When I invoke User method, it throw exception:
Method not found: 'Void B.Entities.User.set_Status(A.Entities.Status)'.
Why? I hope someone can help me, thanks!
I can't reproduce the problem. Your code works fine on my computer (on .NET framework 4.5)
Could you make sure that you project is configured correctly:
Both A and B solutions have reference to System.Runtime.Serialization
C has reference to A and B. Make sure you don't link the dll from /Bin folder, but you have the project reference
Hit Clean and Rebuild buttons in Visual Studio.

Having NUnit console report test results during the test run, after each test

I run NUnit console on my test assembly but sometimes my NUnit crashes (I'm currently figuring out why). When nunit crashes no xml report is created and I effectively am left without any test report. The test run is very long and it's a bad situation if I lose the entire test run report.
Is there a way to tell NUNit to write the xml log file as it goes (after each test). Even if that means the xml file won't be closed properly.
I know it is possible to use NUnit TestListener. But is there a switch or something that does not include writing extra code myself.
You could invoke nunit-console with the /labels command-line switch. This will cause it to write out the (fully-qualified) name of each test to the console as it runs, though the output does not include the test result. However, it would show you which tests had run successfully.
The only other option is the one you have discounted, that of writing your own EventListener implementation. The documentation about that interface is a little light, but the NUnit documentation about writing an NUnit add-in assembly should be enough to get you started if you change your mind about that.
First of all in a near future it looks like such a logging will be provided by NUnit out of the box - this feature was already requested - Write partial results XML as tests happen instead of at the end.
Until its done we need to write some custom code and in case u use NUnit < 3.x its pretty simple:
1)You need to create an event listener which implements EventListener interface
2)This interface provides notifications for different states of test execution eg. RunStarted, RunFinished or TestFinished. All you need to is an implementation of logging relevant for your case. Snippet from my code:
public void RunStarted(string name, int testCount)
{
try
{
_instanceId = Environment.GetEnvironmentVariable("InstanceId");
_buildId = Environment.GetEnvironmentVariable("BuildId");
_browser = Environment.GetEnvironmentVariable("BrowserToTest");
_template = Environment.GetEnvironmentVariable("TemplateToTest");
}
catch { }
}
public void TestFinished(TestResult result)
{
if (result.ResultState == ResultState.Ignored)
{
return;
}
var r = new TestingWorkerData
{
BuildId = _buildId,
InstanceId = _instanceId,
TestName = result.FullName,
Success = result.IsSuccess,
TimeTaken = result.Time.ToString(CultureInfo.InvariantCulture),
Message = result.Message,
StackTrace = result.StackTrace,
Browser = _browser,
Template = _template
};
File.AppendAllLines(#"z:\\results.txt", new[] {JsonConvert.SerializeObject(r)});
}
public class TestingWorkerData
{
public string TestName { get; set; }
public bool Success { get; set; }
public string TimeTaken { get; set; }
public string Message { get; set; }
public string StackTrace { get; set; }
public string InstanceId { get; set; }
public string Browser { get; set; }
public string Template { get; set; }
public string BuildId { get; set; }
}
3)The last thing is creation of NUnit addin:
[NUnitAddin]
public class ProgressReporterNugetAddin : IAddin
{
public bool Install(IExtensionHost host)
{
var listeners = host.GetExtensionPoint("EventListeners");
listeners.Install(new ProgressReporterEventListener());
return true;
}
}
Note:There is a pretty good article http://jimmykeen.net/2015/02/28/logging-test-results-with-nunit/ which covers similar approach and more.Unfortunately it works for NUnit < 3.x ONLY since NUnit3 was heavily rewritten - eg. no EventListener interface anymore.

Categories