Avoid non-readonly static fields - Immutability NDepend - c#

I am using NDepend for code analysis and got this warning:
https://www.ndepend.com/default-rules/NDepend-Rules-Explorer.html?ruleid=ND1901#!
This rule warns about static fields that are not declared as read-only.
In Object-Oriented-Programming the natural artifact to hold states that can be modified is instance fields. Such mutable static fields create confusion about the expected state at runtime and impairs the code testability since the same mutable state is re-used for each test.
My code is as follows:
using Cosmonaut;
using Microsoft.Azure.Documents.Client;
using System.Configuration;
using LuloWebApi.Entities;
namespace LuloWebApi.Components
{
/// <summary>
/// Main class that encapsulates the creation of instances to connecto to Cosmos DB
/// </summary>
public sealed class CosmosStoreHolder
{
/// <summary>
/// Property to be initiated only once in the constructor (singleton)
/// </summary>
private static CosmosStoreHolder instance = null;
/// <summary>
/// To block multiple instance creation
/// </summary>
private static readonly object padlock = new object();
/// <summary>
/// CosmosStore object to get tenants information
/// </summary>
public Cosmonaut.ICosmosStore<SharepointTenant> CosmosStoreTenant { get; }
/// <summary>
/// CosmosStore object to get site collection information
/// </summary>
public Cosmonaut.ICosmosStore<SiteCollection> CosmosStoreSiteCollection { get; }
/// <summary>
/// CosmosStore object to get page templates information
/// </summary>
public Cosmonaut.ICosmosStore<PageTemplate> CosmosStorePageTemplate { get; }
/// <summary>
/// CosmosStore object to get pages information
/// </summary>
public Cosmonaut.ICosmosStore<Page> CosmosStorePage { get; }
/// <summary>
/// CosmosStore object to get roles information
/// </summary>
public Cosmonaut.ICosmosStore<Role> CosmosStoreRole { get; }
/// <summary>
/// CosmosStore object to get clients information
/// </summary>
public Cosmonaut.ICosmosStore<Client> CosmosStoreClient { get; }
/// <summary>
/// CosmosStore object to get users information
/// </summary>
public Cosmonaut.ICosmosStore<User> CosmosStoreUser { get; }
/// <summary>
/// CosmosStore object to get partners information
/// </summary>
public Cosmonaut.ICosmosStore<Partner> CosmosStorePartner { get; }
/// <summary>
/// CosmosStore object to get super administrators information
/// </summary>
public Cosmonaut.ICosmosStore<SuperAdministrator> CosmosStoreSuperAdministrator { get; }
/// <summary>
/// Constructor
/// </summary>
CosmosStoreHolder()
{
CosmosStoreSettings settings = new Cosmonaut.CosmosStoreSettings(ConfigurationManager.AppSettings["database"].ToString(),
ConfigurationManager.AppSettings["endpoint"].ToString(),
ConfigurationManager.AppSettings["authKey"].ToString());
settings.ConnectionPolicy = new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp
};
CosmosStoreTenant = new CosmosStore<SharepointTenant>(settings);
CosmosStoreSiteCollection = new CosmosStore<SiteCollection>(settings);
CosmosStorePageTemplate = new CosmosStore<PageTemplate>(settings);
CosmosStorePage = new CosmosStore<Page>(settings);
CosmosStoreRole = new CosmosStore<Role>(settings);
CosmosStoreClient = new CosmosStore<Client>(settings);
CosmosStoreUser = new CosmosStore<User>(settings);
CosmosStorePartner = new CosmosStore<Partner>(settings);
CosmosStoreSuperAdministrator = new CosmosStore<SuperAdministrator>(settings);
}
/// <summary>
/// Instance access, singleton
/// </summary>
public static CosmosStoreHolder Instance
{
get
{
lock (padlock)
{
if (instance == null)
{
instance = new CosmosStoreHolder();
}
return instance;
}
}
}
}
}
However I am not sure how to fix this warning.

This is a guide, not a hard rule. Usually, non-readonly static fields are hard to intuit about. But in this case you're doing lazy deferred loading, so... a lock and mutate is indeed one way of achieving that, without causing it to be loaded prematurely.
So a pragmatic fix is: just ignore/override the warning
Another approach, however, is to move the field to another type where it is readonly, and rely on the deferred .cctor semantics:
public static CosmosStoreHolder Instance {
[MethodImpl(MethodImplOptions.NoInlining)]
get => DeferredHolder.Instance;
}
private static class DeferredHolder {
internal static readonly CosmosStoreHolder Instance = new CosmosStoreHolder();
}
Then you don't even need the lock semantics (.cctor deals with that for you).

Related

Converter file section is null

I'm making a BRRES to BFRES converter. For some reason, the MDL0 section seems to be always null when debugging. Here is the code for the Brres file loader:
/// <summary>
/// Represents a set of properties controlling the load of a <see cref="Brres.BrresFile"/>.
/// </summary>
internal class BrresLoaderContext
{
// ---- CONSTRUCTORS -------------------------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the <see cref="BrresLoaderContext"/> class for the given <see cref="BrresFile"/>
/// instance using the given <see cref="BinaryDataReader"/>.
/// </summary>
/// <param name="BrresFile">The <see cref="BrresFile"/> instance to load the data in.</param>
/// <param name="reader">The <see cref="BinaryDataReader"/> to use for reading the data.</param>
internal BrresLoaderContext(BrresFile brresFile, BinaryDataReader reader)
{
BrresFile = brresFile;
Reader = reader;
Warnings = new List<string>();
}
// ---- PROPERTIES ---------------------------------------------------------------------------------------------
/// <summary>
/// Gets the <see cref="BrresFile"/> instance which is loaded to.
/// </summary>
internal BrresFile BrresFile
{
get;
private set;
}
/// <summary>
/// Gets the <see cref="BinaryDataReader"/> which is used to read data from the input stream.
/// </summary>
internal BinaryDataReader Reader
{
get;
private set;
}
/// <summary>
/// Gets or sets the warnings raised after loading the Brres file.
/// </summary>
internal List<string> Warnings
{
get;
private set;
}
}
I mostly didn't update comments.
So why is it null?

How to make a call-back timer thread-safe if the code-execution time is not static or always known?

I'm newer to coding, as a warning not an excuse. I currently have a quick timer class 'wrapper' I use. While most of the time I've used it, it worked as expected, I now have an issue.
The code the timer calls back does not always have a set or even accurate estimate of how long it will take to execute that chunk of code start to finish. This leaves me with abnormally long timer update intervals to account for it, or, alternatively stop the timer, and start it again each time it 'ticks' to prevent over-lap.
I've found the first method unacceptable in my case. The second one sounded perfect, but when I tried it it slowed down the code a lot and could have easily ticked much more often after I reviewed it. I'm not sure why it slows it down so much.
Should I look at another way at doing this, besides timers, like some kind of manual control over the flow of events? This is for a simple game-update loop class. Here is said class in full below.
public class TimedUpdater<T>
{
#region Public Delegates/Events
/// <summary>
/// An event that is raised repeatedly at the Interval[in milliseconds] for this Instance.
/// </summary>
public event EventHandler<T> OnUpdate;
#endregion
#region Fields, Private Properties
private Timer Timer { get; }
private TimerCallback Callback { get; }
private T State { get; }
#endregion
#region Constructors, Destructors
/// <summary>
/// Initializes a new instance of the <see cref="TimedUpdater{T}" /> class.
/// </summary>
/// <param name="state">The state object to use for updating data.</param>
/// <param name="name">The unique name representing this instance.</param>
/// <param name="updateRateMs">The rate the the <code>OnUpdate</code> event is raised in milliseconds.</param>
public TimedUpdater(T state, string name, int updateRateMs)
{
Name = name;
Interval = updateRateMs;
State = state;
Callback += Process;
Timer = new Timer(Callback, State, Timeout.Infinite, Timeout.Infinite);
}
/// <summary>
/// Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage
/// collection.
/// </summary>
~TimedUpdater()
{
Dispose();
}
#endregion
#region Public Properties, Indexers
/// <summary>
/// Gets or sets the interval in milliseconds.
/// </summary>
/// <value>The interval in milaseconds.</value>
public int Interval { get; set; }
/// <summary>
/// States if the updater is enabled.
/// </summary>
public bool IsEnabled { get; private set; }
/// <summary>
/// Gets the unique name that represents this instance.
/// </summary>
/// <value>The name.</value>
public string Name { get; }
#endregion
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
Disable();
Timer.Dispose();
}
/// <summary>
/// Enables the updater.
/// </summary>
public void Enable()
{
Timer.Change(Interval, Interval);
IsEnabled = true;
}
/// <summary>
/// Disables the updater.
/// </summary>
public void Disable()
{
Timer.Change(int.MaxValue, Interval);
IsEnabled = false;
}
/// <summary>
/// Processes the specified object casted to the type.
/// </summary>
/// <param name="e">The e.</param>
protected virtual void Process(object e)
{
OnUpdate?.Invoke(this, (T) e);
}
}

Pass Exception and Subclasses over NamedPipe

I'm trying to pass objects of type Exception (or one of it's subclasses) over a NamedPipe.
ServiceContract:
[ServiceContract]
public interface IWCFCallback
{
[OperationContract]
void sendException(Exception e);
}
it works fine when i use it like this:
_pipeproxy.sendException(new Exception("bla bla 99"));
but as soon as I pass a subclass:
_pipeproxy.sendException(new ArgumentException("fridgemaster 3000"));
I get a Exception, saying deserialisation failed.
I already read about the KnownTypes Attribute, but i can't figure out how to use it for classes not implemented by myself.
Can someone give me a hint here?
One of the "Best practices" over WCF, is Do not serialize Exception.
If your ServiceHost is throwing exception, then you are suppose to use FaultException.
One of the reason why exception is not safe to transfer, is that Exception itself is serializable, but you can derive from it, and who guarantee that your custom derived exception will be serialable.
You could pass a Data contract object with the exception stack as string and type as enum, as a work-around.
This may not be according to the best practices but you can create a DataContract that represents the Exception - something like this:
/// <summary>
/// Represents errors that occur during application execution.
/// </summary>
[DataContract]
public class ExceptionInfo
{
/// <summary>
/// Gets the type of the exception.
/// </summary>
[DataMember]
public string ExceptionType
{
get;
set;
}
/// <summary>
/// Gets a message that describes the current exception.
/// </summary>
/// <returns>
/// The error message that explains the reason for the exception, or an empty string("").
/// </returns>
[DataMember]
public string Message
{
get;
set;
}
/// <summary>
/// Gets the <see cref="T:System.Exception"/> instance that caused the current exception.
/// </summary>
/// <returns>
/// An instance of Exception that describes the error that caused the current exception. The InnerException property returns the same value as was passed into the constructor, or a null reference (Nothing in Visual Basic) if the inner exception value was not supplied to the constructor. This property is read-only.
/// </returns>
[DataMember]
public ExceptionInfo InnerException
{
get;
set;
}
/// <summary>
/// Gets a string representation of the immediate frames on the call stack.
/// </summary>
/// <returns>
/// A string that describes the immediate frames of the call stack.
/// </returns>
[DataMember]
public string StackTrace
{
get;
set;
}
/// <summary>
/// Gets or sets a link to the help file associated with this exception.
/// </summary>
/// <returns>
/// The Uniform Resource Name (URN) or Uniform Resource Locator (URL).
/// </returns>
[DataMember]
public string HelpLink
{
get;
set;
}
/// <summary>
/// Gets or sets the name of the application or the object that causes the error.
/// </summary>
[DataMember]
public string Source
{
get;
set;
}
/// <summary>
/// Initializes a new instance of the <see cref="ExceptionInfo"/> class.
/// </summary>
/// <param name="exception">The exception.</param>
/// <exception cref="ArgumentNullException">exception</exception>
public ExceptionInfo(Exception exception)
{
if(exception == null)
throw new ArgumentNullException("exception");
ExceptionType = exception.GetType().FullName;
HelpLink = exception.HelpLink;
Message = exception.Message;
Source = exception.Source;
StackTrace = exception.StackTrace;
if(exception.InnerException != null)
{
InnerException = new ExceptionInfo(exception.InnerException);
}
}
}
Service Contract:
[ServiceContract]
public interface IWCFCallback
{
[OperationContract]
void sendException(ExceptionInfo e);
}
Usage:
try
{
// .....
}
catch (Exception ex)
{
var info = new ExceptionInfo(ex);
// do something....
}

Datagrid + Map column to struct fields

I'm trying to bind a datagrid (WPF C# 4.0 with WPF Toolkit) to the fields of a structure. I basically have a datagrid with two columns. The first I would like to be labels, the second I would like to be the members of a structure. Perferably I would like to treat the series of rows as a single structure which can then be used elsewhere in my program.
Currently I have the program adding new instances of some class for each row, but I would prefer to treat it all as one... is there a way?
Thanks
ViewModel
/// <summary>
/// DataGridRowViewModel
/// </summary>
public class DataGridRowViewModel:BaseViewModel
{
/// <summary>
/// structureField
/// </summary>
private string structureField;
private string lableText;
/// <summary>
/// StructureField
/// </summary>
public string StructureField
{
get { return structureField; }
set
{
structureField= value;
OnPropertyChanged("StructureField");
}
}
/// <summary>
/// StructureField
/// </summary>
public string LableText
{
get { return lableText; }
set
{
lableText= value;
OnPropertyChanged("LableText");
}
}
}
/// <summary>
/// DataGridRowViewModel
/// </summary>
public class MainViewModel:BaseViewModel
{
/// <summary>
/// structureField
/// </summary>
private ObservableCollection<DataGridRowViewModel> rowCollection;
//Make Property with INotifyPropertyChanged
/// <summary>
/// Default Constructor
/// </summary>
public MainViewModel()
{
RowCollection = new ObservableCollection<DataGridRowViewModel>();
FillCollectionWithStructureFields();
}
private void FillCollectionWithStructureFields()
{
//Fill Add New Instances of DataGridRowViewModel with required Label
// and Structure Filead Values
}
}
View
Bind the collection to DataGrid with required Columns...

Create an Xml file from an object

I work as a web developer with a web designer and we usually do like this :
- I create the system , I generate some Xml files
- the designer display the xml files with xslt
Nothing new.
My problem is that I use Xml Serialization to create my xml files, but I never use Deserialization. So I'd like to know if there is a way to avoid fix like these :
empty setter for my property
empty parameter-less constructor
implement IXmlSerializable and throw "notimplementedexception" on deserialization
do a copy of the class with public fields
Ok mis-read your question first time around! Pretty sure there is no way to avoid this. There has to be a parameterless constructor and you can't serialize readonly properties. I think your only other option is DataContractSerializer.
http://blogs.mastronardi.be/Sandro/2007/08/22/CustomXMLSerializerBasedOnReflectionForSerializingPrivateVariables.aspx
This article describes creating a custom XML serialiser so you can serialise private fields - it may take a little bit of moulding to the form that you want, but it's easier than it looks (honest!) and it's a good start to writing your own serialiser / deserialiser that will serialise exactly what you want - and doesn't care about parameterless constructors or writeable properties.
The only other solution I can think of is to make a wrapper class for every serialisable class - but I don't know how good that would be in the long run. I just get the impression it's not good.
I know you don't want to add a parameterless constructor nor setters, but that's the only way to go with using the XmlSerializer. The good news is the parameterless constructor can be private and the setters can be empty and serialization will work. See thus:
namespace Aesop.Dto
{
using System;
using System.Xml.Serialization;
/// <summary>
/// Represents an Organization ID/Name combination.
/// </summary>
[Serializable]
public sealed class Org
{
/// <summary>
/// The organization's name.
/// </summary>
private readonly string name;
/// <summary>
/// The organization's ID.
/// </summary>
private readonly int id;
/// <summary>
/// Initializes a new instance of the <see cref="Org"/> class.
/// </summary>
/// <param name="name">The organization's name.</param>
/// <param name="id">The organization's ID.</param>
public Org(string name, int id)
{
this.name = name;
this.id = id;
}
/// <summary>
/// Prevents a default instance of the <see cref="Org"/> class from
/// being created.
/// </summary>
private Org()
{
}
/// <summary>
/// Gets or sets the organization's name.
/// </summary>
/// <value>The organization's name.</value>
[XmlAttribute]
public string Name
{
get
{
return this.name;
}
set
{
}
}
/// <summary>
/// Gets or sets the organization's ID.
/// </summary>
/// <value>The organization's ID.</value>
[XmlAttribute]
public int ID
{
get
{
return this.id;
}
set
{
}
}
}
}
Ok now i understand it. I don't think there can be any way to do it with XMLSerialization.
XMLSerialization need these information to re-populate the object. It does not know that some user never deserialize data. You might have to write some code to generate XML for your objects.
class Preferences
{
private const string filePreferences = "preferences.xml";
public Preferences() { }
public static Preferences Load()
{
Preferences pref = null;
if (File.Exists(Preferences.FileFullPath))
{
var serializer = new System.Xml.Serialization.XmlSerializer(typeof(Preferences));
using (var xmlReader = new System.Xml.XmlTextReader(Preferences.FileFullPath))
{
if (serializer.CanDeserialize(xmlReader))
{
pref = serializer.Deserialize(xmlReader) as Preferences;
}
}
}
return ((pref == null) ? new Preferences() : pref);
}
public void Save()
{
var preferencesFile = FileFullPath;
var preferencesFolder = Directory.GetParent(preferencesFile).FullName;
using (var fileStream = new FileStream(preferencesFile, FileMode.Create))
{
new System.Xml.Serialization.XmlSerializer(typeof(Preferences)).Serialize(fileStream, this);
}
}
}

Categories

Resources