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

Form analysis 1 forms found in the DOM

POST ./

<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&amp;t=637906577474367579" type="text/javascript"></script>
  <script src="/WebResource.axd?d=Fa56g0mQFD8Dl7HzHJ0yDaIwZ-iiAIwmZCMskbjXaFrz25McdUFORtxzlG4mXLBPUT-F7T9PR9UPbuoOjZZmYdgB3yUM3gaU5aSCITlIf8Y1&amp;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&amp;k=6LfgqCkdAAAAAJO0HnSwDOqQ-Dqc1KU8k3bRn3FF&amp;co=aHR0cHM6Ly93d3cucG9zdHNoYXJwLm5ldDo0NDM.&amp;hl=en&amp;v=5qcenVbrhOy8zihcc2aHOWD4&amp;size=invisible&amp;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(&quot;ctl00$BodyPlaceHolder$ctl16$newsletterForm$submitButton&quot;, &quot;&quot;, true, &quot;&quot;, &quot;&quot;, 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