www.postsharp.net
Open in
urlscan Pro
13.107.237.59
Public Scan
URL:
https://www.postsharp.net/
Submission: On January 08 via manual from NZ — Scanned from NZ
Submission: On January 08 via manual from NZ — Scanned from NZ
Form analysis
1 forms found in the DOMPOST ./
<form method="post" action="./" onsubmit="javascript:return WebForm_OnSubmit();" id="aspnetForm">
<div class="aspNetHidden">
<input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="">
<input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTIwODQxNTQ0MDlkZLcQ6PbIVbGkHkNrLpzqeUoHEw3JHUb1PRoX4S7wF0cf">
</div>
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['aspnetForm'];
if (!theForm) {
theForm = document.aspnetForm;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
<script src="/WebResource.axd?d=_dEwmRoh4VO1GyqYn3CHqChvmYw_qB4h1AszztGlE7JRomJ4zgWDcVhAhClLDREu1CpQ-r5WaH-hhm9FS0cUNoZhu3y_2syL_JSlqtb4qO01&t=637906577474367579" type="text/javascript"></script>
<script src="/WebResource.axd?d=Fa56g0mQFD8Dl7HzHJ0yDaIwZ-iiAIwmZCMskbjXaFrz25McdUFORtxzlG4mXLBPUT-F7T9PR9UPbuoOjZZmYdgB3yUM3gaU5aSCITlIf8Y1&t=637906577474367579" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
function WebForm_OnSubmit() {
if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false) return false;
return true;
}
//]]>
</script>
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="8D0E13E6">
<input type="hidden" name="__SCROLLPOSITIONX" id="__SCROLLPOSITIONX" value="0">
<input type="hidden" name="__SCROLLPOSITIONY" id="__SCROLLPOSITIONY" value="0">
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEdAAOC78Cno1hlsYNCa0HPw5ETYBq8OVkdDLg+DKnActw1OjTFumlx9XysHHLr6FbR9/EyonEfJeGbROcSe8ixXFgQ7OyNhC8la8Df7KtUUkVwDg==">
</div>
<div class="row no-gutters">
<div class="col">
<input name="ctl00$BodyPlaceHolder$ctl16$newsletterForm$emailTextBox" id="ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailTextBox" class="largeInputField large w-100 h-100" placeholder="Your email" type="email">
</div>
<div class="g-recaptcha" data-sitekey="6LfgqCkdAAAAAJO0HnSwDOqQ-Dqc1KU8k3bRn3FF" data-callback="DoSubcribe" data-size="invisible">
<div class="grecaptcha-badge" data-style="bottomright"
style="width: 256px; height: 60px; display: block; transition: right 0.3s ease 0s; position: fixed; bottom: 14px; right: -186px; box-shadow: gray 0px 0px 5px; border-radius: 2px; overflow: hidden;">
<div class="grecaptcha-logo"><iframe title="reCAPTCHA"
src="https://www.google.com/recaptcha/api2/anchor?ar=1&k=6LfgqCkdAAAAAJO0HnSwDOqQ-Dqc1KU8k3bRn3FF&co=aHR0cHM6Ly93d3cucG9zdHNoYXJwLm5ldDo0NDM.&hl=en&v=5qcenVbrhOy8zihcc2aHOWD4&size=invisible&cb=pz7ziumlxpyu"
width="256" height="60" role="presentation" name="a-3i5w9dtl29uq" frameborder="0" scrolling="no" sandbox="allow-forms allow-popups allow-same-origin allow-scripts allow-top-navigation allow-modals allow-popups-to-escape-sandbox"></iframe>
</div>
<div class="grecaptcha-error"></div><textarea id="g-recaptcha-response" name="g-recaptcha-response" class="g-recaptcha-response"
style="width: 250px; height: 40px; border: 1px solid rgb(193, 193, 193); margin: 10px 25px; padding: 0px; resize: none; display: none;"></textarea>
</div><iframe style="display: none;"></iframe>
</div>
<div class="col-auto">
<input type="submit" name="ctl00$BodyPlaceHolder$ctl16$newsletterForm$submitButton" value="SUBSCRIBE"
onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$BodyPlaceHolder$ctl16$newsletterForm$submitButton", "", true, "", "", false, false))"
id="ctl00_BodyPlaceHolder_ctl16_newsletterForm_submitButton" class="btn btn--blue">
</div>
</div>
<div class="row">
<div class="col">
<p class="grecaptcha-terms"> This site is protected by reCAPTCHA and the Google <a href="https://policies.google.com/privacy">Privacy Policy</a> and <a href="https://policies.google.com/terms">Terms of Service</a> apply. </p>
</div>
</div>
<div class="row">
<div class="col">
<span id="ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailRequiredFieldValidator" class="validation-error customerInfo" style="display:none;">This field is required.</span>
<span id="ctl00_BodyPlaceHolder_ctl16_newsletterForm_RegularExpressionValidator1" class="validation-error customerInfo" style="display:none;">This is not a valid email address.</span>
</div>
</div>
<script type="text/javascript">
//<![CDATA[
var Page_Validators = new Array(document.getElementById("ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailRequiredFieldValidator"), document.getElementById("ctl00_BodyPlaceHolder_ctl16_newsletterForm_RegularExpressionValidator1"));
//]]>
</script>
<script type="text/javascript">
//<![CDATA[
var ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailRequiredFieldValidator = document.all ? document.all["ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailRequiredFieldValidator"] : document.getElementById(
"ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailRequiredFieldValidator");
ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailRequiredFieldValidator.controltovalidate = "ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailTextBox";
ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailRequiredFieldValidator.errormessage = "This field is required.";
ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailRequiredFieldValidator.display = "Dynamic";
ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailRequiredFieldValidator.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid";
ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailRequiredFieldValidator.initialvalue = "";
var ctl00_BodyPlaceHolder_ctl16_newsletterForm_RegularExpressionValidator1 = document.all ? document.all["ctl00_BodyPlaceHolder_ctl16_newsletterForm_RegularExpressionValidator1"] : document.getElementById(
"ctl00_BodyPlaceHolder_ctl16_newsletterForm_RegularExpressionValidator1");
ctl00_BodyPlaceHolder_ctl16_newsletterForm_RegularExpressionValidator1.controltovalidate = "ctl00_BodyPlaceHolder_ctl16_newsletterForm_emailTextBox";
ctl00_BodyPlaceHolder_ctl16_newsletterForm_RegularExpressionValidator1.errormessage = "This is not a valid email address.";
ctl00_BodyPlaceHolder_ctl16_newsletterForm_RegularExpressionValidator1.display = "Dynamic";
ctl00_BodyPlaceHolder_ctl16_newsletterForm_RegularExpressionValidator1.evaluationfunction = "RegularExpressionValidatorEvaluateIsValid";
ctl00_BodyPlaceHolder_ctl16_newsletterForm_RegularExpressionValidator1.validationexpression = "\\w+([-+.\']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
//]]>
</script>
<script type="text/javascript">
//<![CDATA[
var Page_ValidationActive = false;
if (typeof(ValidatorOnLoad) == "function") {
ValidatorOnLoad();
}
function ValidatorOnSubmit() {
if (Page_ValidationActive) {
return ValidatorCommonOnSubmit();
} else {
return true;
}
}
theForm.oldSubmit = theForm.submit;
theForm.submit = WebForm_SaveScrollPositionSubmit;
theForm.oldOnSubmit = theForm.onsubmit;
theForm.onsubmit = WebForm_SaveScrollPositionOnSubmit;
//]]>
</script>
</form>
Text Content
PostSharp * PostSharp.IL * Metalama * Community * Company PostSharp * PostSharp.IL * Overview * Products * Overview * Framework * MVVM * Logging * Threading * Caching * Ultimate * Essentials * Download * Docs * Support * Pricing * Products * Compare * Renewals * Special Offers * Team Trial * FAQ * Contact Us * FREE EDITION * Metalama * Overview * Features * Download * Docs * Support * Pricing * FREE EDITION * Community * Company * About Us * Customers * Resellers * Contact Us * Legal * Blog * Contact Login Your cart try it for free LESS BOILERPLATE MORE CLARITY We build meta-programming tools for .NET that reduce boilerplate and architecture erosion. TWO GENERATIONS OF .NET TECHNOLOGIES The proven MSIL-based aspect-oriented framework since 2005. * Based on post-compilation MSIL transformation. * Supports platforms back to VS 2017, .NET 3.5, .NET Core 3.1. * Supports VS 2022, .NET 4.8 and .NET 6. * Rich library of ready-made aspects. * Full-featured PostSharp Tools for Visual Studio * Limited design-time support. * Limited support for Xamarin, Blazor. SEE MORE A modern Roslyn-based meta-programming framework. * Built with Roslyn for modern .NET. * Works with any platform supporting .NET Standard 2.0. * Full design-time experience with source generators. * Custom code fixes, live templates. * Requires VS 2022, .NET 4.7 or .NET 5. * Library of ready-made aspects under development. * Metalama Tools for Visual Studio still limited. SEE MORE WHAT ARE BOILERPLATE AND ARCHITECTURE EROSION COSTING YOU? A TOTAL WASTE OF YOUR TIME Manually writing boilerplate is not only boring and frustrating, it is a total waste of your time. Why do manually what a machine can do better and faster? Although allowing architecture to erode initially saves time, but as it progressively accumulates, it makes everybody on the team less productive. EXCESSIVE COMPLEXITY Your business logic is unreadable because it is littered with boilerplate and the source code becomes so complex that your brain can no longer make sense of it. As source code derives from the original architecture, more and more exceptions to the rule are committed, and the conceptual complexity of the source code increases. AVOIDABLE DEFECTS Boilerplate is littered with bugs because it's created by copy-paste programming and mostly remains untested. Production-readiness features such as logging or caching are neglected because they are too expensive to build without the proper tooling. As your codebase complexity increases its overall quality suffers: end-users experience bugs and performance degrades. EXPENSIVE MAINTENANCE With both boilerplate and architecture erosion increasing complexity, it becomes more and more expensive to make small changes in your application. A bigger refactoring becomes completely impossible, and you need to rewrite your whole codebase from scratch. Smart use of meta-programming could extend the lifetime of your codebase by several years. TOP-RATED VS EXTENSION OVER 7.5M DOWNLOADS SERVING CUSTOMERS SINCE 2005 ASPECTS: OUR CORE TECHNOLOGY Aspects are special C# classes execute inside the compiler or the IDE and can: * enhance your source code at compile-time or in the IDE, * validate your source code and emit errors or warnings, * suggest code fixes and refactorings. THE RESULT: YOUR CODE IS SHORTER AND CLEANER. Without PostSharp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 public class Address : INotifyPropertyChanged { private string _line1; private string _line2; private string _city; private string _remark; public string Line1 { get => _line1; set { _line1 = value; OnPropertyChanged(); OnPropertyChanged(nameof(FullAddress)); } } public string Line2 { get => _line2; set { _line2 = value; OnPropertyChanged(); OnPropertyChanged(nameof(FullAddress)); } } public string City { get => _city; set { _city = value; OnPropertyChanged(); OnPropertyChanged(nameof(FullAddress)); } } public string Remark { get => _remark; set { _remark = value; OnPropertyChanged(); } } public string FullAddress => string.Join(Environment.NewLine, Line1, Line2, City); public event PropertyChangedEventHandler PropertyChanged; // TODO: Weak event. protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class Person : INotifyPropertyChanged { private string _firstName; private string _lastName; private Address _address; public string FirstName { get => _firstName; set { _firstName = value; OnPropertyChanged(); } } public string LastName { get => _lastName; set { _lastName = value; OnPropertyChanged(); } } public Address Address { get => _address; set { _address = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; // TODO: Weak event. protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class PersonViewModel : INotifyPropertyChanged { private Person _person; private bool _includeAddressInDetails; // TODO: Weak reference (if weak events are implemented). private Address _observedAddress; public Person Person { get => _person; set { if (_person != null) { _person.PropertyChanged -= OnPersonPropertyChanged; if (_observedAddress != null) { _observedAddress.PropertyChanged -= OnAddressPropertyChanged; _observedAddress = null; } } _person = value; if (value != null) { value.PropertyChanged += OnPersonPropertyChanged; _observedAddress = value.Address; if (_observedAddress != null) { _observedAddress.PropertyChanged += OnAddressPropertyChanged; } } OnPropertyChanged(); OnPropertyChanged(nameof(FullDetails)); } } private void OnAddressPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == nameof(Address.FullAddress)) { OnPropertyChanged(nameof(FullDetails)); } } private void OnPersonPropertyChanged(object sender, PropertyChangedEventArgs e) { switch (e.PropertyName) { case nameof(Person.FirstName): case nameof(Person.LastName): OnPropertyChanged(nameof(FullDetails)); break; case nameof(Person.Address): if (_observedAddress != null) { _observedAddress.PropertyChanged -= OnAddressPropertyChanged; _observedAddress = null; } _observedAddress = _person.Address; if (_observedAddress != null) { _observedAddress.PropertyChanged += OnAddressPropertyChanged; } break; } } public bool IncludeAddressInDetails { get => _includeAddressInDetails; set { _includeAddressInDetails = value; OnPropertyChanged(); OnPropertyChanged(nameof(FullDetails)); } } public string FullDetails { get { // We don't handle the nulls for simplicity of the argument. if (IncludeAddressInDetails) { return string.Join(this.Person.FirstName + " " + this.Person.LastName, this.Person.Address.FullAddress); } else { return this.Person.FirstName + " " + this.Person.LastName; } } } public event PropertyChangedEventHandler PropertyChanged; // TODO: Weak events. [NotifyPropertyChangedInvocator] protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } With PostSharp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 [NotifyPropertyChanged] public class Address { public string Line1 { get; set; } public string Line2 { get; set; } public string City { get; set; } public string Remark { get; set; } public string FullAddress => string.Join(Environment.NewLine, Line1, Line2, City); } [NotifyPropertyChanged] public class Person { public string FirstName { get; set; } public string LastName { get; set; } public Address Address { get; set; } } [NotifyPropertyChanged] public class PersonViewModel { public Person Person { get; set; } public bool IncludeAddressInDetails { get; set; } public string FullDetails { get { // We don't handle the nulls for simplicity of the argument. if (IncludeAddressInDetails) { return string.Join(this.Person.FirstName + " " + this.Person.LastName, this.Person.Address.FullAddress); } else { return this.Person.FirstName + " " + this.Person.LastName; } } } } Without PostSharp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 public partial class MainWindow : Window { private MainViewModel _mainViewModel = new MainViewModel(); public MainWindow() { InitializeComponent(); this.OpenFile = new OpenFileCommand(_mainViewModel); this.CloseFile = new CloseFileCommand(_mainViewModel); } public ICommand OpenFile { get; } public ICommand CloseFile { get; } class OpenFileCommand : ICommand { private MainViewModel _mainViewModel; public OpenFileCommand(MainViewModel mainViewModel) { _mainViewModel = mainViewModel; } public bool CanExecute(object parameter) => true; public void Execute(object parameter) => _mainViewModel.OpenFile(); public event EventHandler CanExecuteChanged; } class CloseFileCommand : ICommand { private MainViewModel _mainViewModel; public CloseFileCommand(MainViewModel mainViewModel) { _mainViewModel = mainViewModel; _mainViewModel.PropertyChanged += delegate (object o, PropertyChangedEventArgs args) { if (args.PropertyName == nameof(MainViewModel.IsFileOpen)) { this.CanExecuteChanged?.Invoke(this, EventArgs.Empty); } }; } public bool CanExecute(object parameter) => _mainViewModel.IsFileOpen; public void Execute(object parameter) => _mainViewModel.CloseFile(); public event EventHandler CanExecuteChanged; } } public partial class FancyTextBlock : UserControl { public static DependencyProperty TextProperty = DependencyProperty.Register( "Text", typeof(string), typeof(FancyTextBlock), null, value => !string.IsNullOrEmpty(value as string)); public string Text { get => (string)this.GetValue(TextProperty); set => this.SetValue(TextProperty, value); } } With PostSharp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public partial class MainWindow : Window { private MainViewModel _mainViewModel = new MainViewModel(); public MainWindow() { InitializeComponent(); } [Command] public ICommand OpenFile { get; private set; } private void ExecuteOpenFile() => _mainViewModel.OpenFile(); [Command] public ICommand CloseFile { get; private set; } private void ExecuteCloseFile() => _mainViewModel.CloseFile(); public bool CanExecuteCloseFile => _mainViewModel.IsFileOpen; } public partial class FancyTextBlock : UserControl { [DependencyProperty, Required] public string Text { get; set; } } Without PostSharp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 public class Icecream : IFreezable { private double _temperature; public FreezableList<Ingredient> Ingredients { get; } = new FreezableList<Ingredient>(); public double Temperature { get => _temperature; set { if (this.IsFrozen) throw new ObjectReadOnlyException(); _temperature = value; } // Hello, world. } public void Freeze() { this.IsFrozen = true; this.Ingredients.Freeze(); } public bool IsFrozen { get; private set; } } public class Ingredient : IFreezable { private string _name; private double _quantity; public string Name { get => _name; set { if (this.IsFrozen) throw new ObjectReadOnlyException(); _name = value; } } public double Quantity { get => _quantity; set { if (this.IsFrozen) throw new ObjectReadOnlyException(); _quantity = value; } } public void Freeze() { this.IsFrozen = true; } public bool IsFrozen { get; private set; } } With PostSharp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [Freezable] public class Icecream { public FreezableList<Ingredient> Ingredients { get; } = new FreezableList<Ingredient>(); public double Temperature { get; set; } } [Freezable] public class Ingredient { public string Name { get; set; } public double Quantity { get; set; } } Without PostSharp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class UserNameService { private Logger logger; private Db db; // It's just one method, but you should do this for thousands. public string GetUserName(int userId) { var methodLogger = logger.Start("UserNameService.GetUserName({userId})"); try { string userName = db.Context.Users.Single(u => u.Id == userId).Name; methodLogger.Success(userName); return userName; } catch (Exception e) { methodLogger.Exception(e); throw; } } } With PostSharp 1 2 3 4 5 6 7 8 9 10 11 public class UserNameService { private Db db; // Logging is generally configured in an xml config file. public string GetUserName(int userId) { return db.Context.Users.Single(u => u.Id == userId).Name; } } Without PostSharp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 public interface IBananaFactory { Banana GetBanana(string kind, double length, double diameter); } public class BananaFactory : IBananaFactory { public Banana GetBanana(string kind, double length, double diameter) { if (string.IsNullOrEmpty(kind)) throw new ArgumentNullException(nameof(kind)); if (length < 0) throw new ArgumentOutOfRangeException(nameof(length)); // Yep copy-pase error again. if (length < 0 || diameter > 5) throw new ArgumentOutOfRangeException(nameof(length)); return new Banana(kind, length, diameter); } } public class Banana { private string _kind; private double _length; private double _diameter; public Banana(string kind, double length, double diameter) { Kind = kind; Length = length; Diameter = diameter; } public string Kind { get => _kind; set { if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value)); _kind = value; } } public double Length { get => _length; set { if (value < 0) throw new ArgumentOutOfRangeException(nameof(value)); _length = value; } } public double Diameter { get => _diameter; set { if (value < 0 || value > 5) throw new ArgumentOutOfRangeException(nameof(value)); _diameter = value; } } } With PostSharp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public interface IBananaFactory { Banana GetBanana([Required] string kind, [Positive] double length, [Range(0, 5)] double diameter); } public class BananaFactory : IBananaFactory { public Banana GetBanana(string kind, double length, double diameter) { return new Banana(kind, length, diameter); } } public class Banana { public Banana(string kind, double length, double diameter) { Kind = kind; Length = length; Diameter = diameter; } [Required] public string Kind { get; set; } [Positive] public double Length { get; set; } [Range(0, 5)] public double Diameter { get; set; } } n class="codePunctuation">} INPC XAML THREADING LOGGING CONTRACTS SUCCESS STORIES Siemens Audiology ATS Global Thales Gamesys CognitiveX SIEMENS AUDIOLOGY Siemens Audiology saved 15% development time plus improved code readability by removing unwanted boilerplate code. When the team at Siemens Audiology was tasked with building a new WPF implementation for two of its leading hearing system software applications, a big challenge was to find a way to save coding time for developers implementing ViewModels while increasing code readability. download STUDY SEE ALL CASE STUDIES ATS GLOBAL ATS Global saves 16% lines of code. When the team at ATS Global needed to build a complex shop floor simulation, they faced the challenge of potential multithreading issues and the complexity of writing synchronization code. The team turned to PostSharp and was able to write thread-safe code without training all team members in advanced multithreading and delivered required features with 16% fewer lines of code. download STUDY SEE ALL CASE STUDIES THALES INFORMATION SYSTEMS Thales is more focused on business logic. When the team at Thales Information Systems was tasked with a big refactoring on a project, one of the challenges was to simplify architecture by reducing boilerplate code. The architect chose PostSharp to implement custom aspects to handle logging, performance counters and INotifyPropertyChanged and keep junior team members better focused on business logic. SEE FULL VIDEO SEE ALL CASE STUDIES GAMESYS Gamesys improves productivity with PostSharp. Gamesys serves around one million daily active users across its social games. Their backend services handle more than 250 million requests per day. Despite its massive scale, this distinctive service is being maintained by a remarkably small development team of just seven super-productive individuals. download STUDY SEE ALL CASE STUDIES COGNITIVE X SOLUTIONS PostSharp took care of 95% of CognitiveX's INPC code. When Cognitive X was looking for ways to deliver value to their clients while differentiating themselves from the competition, the team chose PostSharp as one of the core pieces of their strategy. By decreasing the actual lines of code they were writing, as well as helping them enforce best practices, PostSharp allowed them to produce new features for their clients faster, at lower cost, and with fewer errors. SEE FULL VIDEO SEE ALL CASE STUDIES START REDUCING BOILERPLATE AND ARCHITECTURE EROSION TODAY. Our proven aspect-oriented framework for C# based on MSIL post-compilation. Since 2005. SEE MORE Our new implementation based on Roslyn with enhanced platform support, better design-time experience, and a lot more. SEE MORE FEATURED FROM THE BLOG OVER 50,000 SATISFIED USERS SEE MORE "POSTSHARP IS VERY EASY TO USE." Releasing developers from writing boilerplate or infrastructure code helps my team to complete features faster. We definitely save coding time with PostSharp. We’re relieved from writing INotifyPropertyChanged and creating ICommand properties needed for data binding. Bernd Hengelein Software Architect, Siemens Audiology "POSTSHARP IS A PRETTY AMAZING PIECE OF SOFTWARE." Stay DRY with aspect oriented programming by injecting repetitive code directly into your application. Abstractions like AOP are the whole point of what the computer is supposed to do for us, work that’s not fun, like logging and transactions. So why not hide that? Scott Hanselman Principal Program Manager, Microsoft "POSTSHARP SHOULD BE PART OF EVERY C# DEVELOPER'S TOOLSET." PostSharp is amazing! If you are not using it, you should! The amount of code that can be reduced in logging alone is worth the price! I believe that PostSharp should be part of EVERY C# developer's toolset. Eric Ziko System Programmer, Wells Fargo "WORKING DECLARATIVELY IS A DREAM!" PostSharp is the best way to implement cross-cutting functionalities in a very elegant and efficient way. And when you want to enforce some design rules in your code, working declaratively is a dream! Pierre-Emmanuel Dautreppe .NET Architect, Thales Information Systems "POSTSHARP SIMPLICITY IS SIMPLY AMAZING." PostSharp rocks! And I mean that as someone who is doing AOP for a long while, and has implemented some not insignificant parts of Castle.DynamicProxy. Leaving aside the amount of power that it gives you, PostSharp simplicity is simply amazing, wow! Oren Eini Author, RhinoMocks "POSTSHARP IS VERY EASY TO USE." Releasing developers from writing boilerplate or infrastructure code helps my team to complete features faster. We definitely save coding time with PostSharp. We’re relieved from writing INotifyPropertyChanged and creating ICommand properties needed for data binding. Bernd Hengelein Software Architect, Siemens Audiology "POSTSHARP IS A PRETTY AMAZING PIECE OF SOFTWARE." Stay DRY with aspect oriented programming by injecting repetitive code directly into your application. Abstractions like AOP are the whole point of what the computer is supposed to do for us, work that’s not fun, like logging and transactions. So why not hide that? Scott Hanselman Principal Program Manager, Microsoft SUBSCRIBE TO OUR NEWSLETTER Stay up to date on all the latest releases, news and discounts. Follow us on social media: This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply. This field is required. This is not a valid email address. PostSharp Proudly built in Prague PostSharp is a registered trade name of SharpCrafters s.r.o. © 2004-2023 Online Support Chat