public class HandleConcurrencyExceptionAttribute : FilterAttribute, IExceptionFilter { private PropertyMatchingMode _propertyMatchingMode; /// <summary> /// This defines when the concurrencyexception happens, /// </summary> public enum PropertyMatchingMode { /// <summary> /// Uses only the field names in the model to check against the entity. This option is best when you are using /// View Models with limited fields as opposed to an entity that has many fields. The ViewModel (or model) field names will /// be used to check current posted values vs. db values on the entity itself. /// </summary> UseViewModelNamesToCheckEntity = 0, /// <summary> /// Use any non-matching value fields on the entity (except timestamp fields) to add errors to the ModelState. /// </summary> UseEntityFieldsOnly = 1, /// <summary> /// Tells the filter to not attempt to add field differences to the model state. /// This means the end user will not see the specifics of which fields caused issues /// </summary> DontDisplayFieldClashes = 2 } public HandleConcurrencyExceptionAttribute() { _propertyMatchingMode = PropertyMatchingMode.UseViewModelNamesToCheckEntity; } public HandleConcurrencyExceptionAttribute(PropertyMatchingMode propertyMatchingMode) { _propertyMatchingMode = propertyMatchingMode; } /// <summary> /// The main method, called by the mvc runtime when an exception has occured. /// This must be added as a global filter, or as an attribute on a class or action method. /// </summary> /// <param name="filterContext"></param> public void OnException(ExceptionContext filterContext) { if (!filterContext.ExceptionHandled && filterContext.Exception is DbUpdateConcurrencyException) { //Get original and current entity values DbUpdateConcurrencyException ex = (DbUpdateConcurrencyException)filterContext.Exception; var entry = ex.Entries.Single(); //problems with ef4.1/4.2 here because of context/model in different projects. //var databaseValues = entry.CurrentValues.Clone().ToObject(); //var clientValues = entry.Entity; //So - if using EF 4.1/4.2 you may use this workaround var clientValues = entry.CurrentValues.Clone().ToObject(); entry.Reload(); var databaseValues = entry.CurrentValues.ToObject(); List<string> propertyNames; filterContext.Controller.ViewData.ModelState.AddModelError(string.Empty, "The record you attempted to edit " + "was modified by another user after you got the original value. The " + "edit operation was canceled and the current values in the database " + "have been displayed. If you still want to edit this record, click " + "the Save button again to cause your changes to be the current saved values."); PropertyInfo[] entityFromDbProperties = databaseValues.GetType().GetProperties(BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Instance); if (_propertyMatchingMode == PropertyMatchingMode.UseViewModelNamesToCheckEntity) { //We dont have access to the model here on an exception. Get the field names from modelstate: propertyNames = filterContext.Controller.ViewData.ModelState.Keys.ToList(); } else if (_propertyMatchingMode == PropertyMatchingMode.UseEntityFieldsOnly) { propertyNames = databaseValues.GetType().GetProperties(BindingFlags.Public).Select(o => o.Name).ToList(); } else { filterContext.ExceptionHandled = true; UpdateTimestampField(filterContext, entityFromDbProperties, databaseValues); filterContext.Result = new ViewResult() { ViewData = filterContext.Controller.ViewData }; return; } UpdateTimestampField(filterContext, entityFromDbProperties, databaseValues); //Get all public properties of the entity that have names matching those in our modelstate. foreach (var propertyInfo in entityFromDbProperties) { //If this value is not in the ModelState values, don't compare it as we don't want //to attempt to emit model errors for fields that don't exist. //Compare db value to the current value from the entity we posted. if (propertyNames.Contains(propertyInfo.Name)) { if (propertyInfo.GetValue(databaseValues, null) != propertyInfo.GetValue(clientValues, null)) { var currentValue = propertyInfo.GetValue(databaseValues, null); if (currentValue == null || string.IsNullOrEmpty(currentValue.ToString())) { currentValue = "Empty"; } filterContext.Controller.ViewData.ModelState.AddModelError(propertyInfo.Name, "Current value: " + currentValue); } } //TODO: hmm.... how can we only check values applicable to the model/modelstate rather than the entity we saved? //The problem here is we may only have a few fields used in the viewmodel, but many in the entity //so we could have a problem here with that. //object o = propertyInfo.GetValue(myObject, null); } filterContext.ExceptionHandled = true; filterContext.Result = new ViewResult() { ViewData = filterContext.Controller.ViewData }; } }
معرفی C# Source Generators
مخلص کلام اینکه : اگه با Fody یا PostSharp و همچنین Code Analyzerها آشنایی دارین. این قابلیت یه چیزی تو مایههای ترکیب ایناس و بهتون اجازه میده موقع Compile شدن کد پروژه رو Analyze کنین و یه کد جدیدی بهش اضافه کنین. (مثلا پیاده سازی اینترفیس INotifyPropertyChanged به صورت خودکار به هنگام کامپایل)
We’re pleased to introduce the first preview of Source Generators, a new C# compiler feature that lets C# developers inspect user code and generate new C# source files that can be added to a compilation. This is done via a new kind of component that we’re calling a Source Generator.
To get started with Source Generators, you’ll need to install the latest .NET 5 preview and the latest Visual Studio preview.
نمونه ای از پیاده سازی INotifyPropertyChanged with C# 9.0 Source Generators
Come learn the top 7 reasons to use Visual Studio 2017 if you are a C++ developer. Whether you are using the product and are looking to upgrade, or you never used it before but you are considering it now, join us to discover how Visual Studio 2017 raises the bar in terms of C++ productivity. From C++ standards conformance to coding productivity, cross-platform development for Windows, Linux, Android, and iOS and CMake support, these are only a few of the topics we discuss in this demo-packed session.
Wikipedia و مهاجرت به HHVM
سایت آموزشی: C# Station
مصاحبه کامل با خالق ++C
Full Interview With the Creator of C++
By popular demand, and a request from the man himself, we’ve decided to release the full interview with esteemed computer scientist Bjarne Stroustrup (aka the creator of C++). We cover a bunch of topics so check the chapters to find what interests you the most! Filmed last year. Enjoy and happy trails!
00:00-02:42 Getting into programming
02:42-03:26 Programming being versatile
03:26-06:07 Industry changes
06:07-10:20 Inventing and maintaining C++
10:20-12:02 Key to making a successful language
12:02-16:04 Greatest lessons
16:14-20:06 Moving to the US
20:06-23:20 Advice to devs