-
-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rule provider not initialized breaks dependency injection principles #70
Comments
Any thoughts on this? |
I don't have time to examine the topic in detail right now, I'll take a look at it when I get the chance |
We just ran into the same issue when trying to update to the latest version. +1 on this suggestion from @merijndejonge:
I think that it's also confusing that we need to manually initialize the Just letting the |
This is how I now solved it. A bit clumsy, but it makes the code more DI-compliant until the library itself is improved: public class DiDomainParser(IRuleProvider ruleProvider, IDomainNormalizer? domainNormalizer = null)
: IDomainParser
{
private readonly DomainParser _domainParser = new(ruleProvider, domainNormalizer);
public DomainInfo? Parse(string fullyQualifiedDomainName)
{
if (ruleProvider.GetDomainDataStructure() == null)
{
ruleProvider.BuildAsync().Wait();
}
return _domainParser.Parse(fullyQualifiedDomainName);
}
public DomainInfo? Parse(Uri fullyQualifiedDomainName)
{
if (ruleProvider.GetDomainDataStructure() == null)
{
ruleProvider.BuildAsync().Wait();
}
return _domainParser.Parse(fullyQualifiedDomainName);
}
public bool IsValidDomain(string fullyQualifiedDomainName)
{
if (ruleProvider.GetDomainDataStructure() == null)
{
ruleProvider.BuildAsync().Wait();
}
return _domainParser.IsValidDomain(fullyQualifiedDomainName);
}
} |
It is not possible for you to initialize your logic like I do here? var ruleProvider = app.Services.GetService<IRuleProvider>();
if (ruleProvider != null)
{
await ruleProvider.BuildAsync();
} |
It requires that a rule provider including dependencies are all registered as singleton services. Why would you want to pose such a strong requirement on a rule provider? |
@tinohager First of all thank you for what you've done here. As I see, this is a common problem. In my opinion, user should not have to dig in the details about any provider object to create a simple DomainParser class as @FlorianHockmann states. Or at least a meaningful error message would also be great, such "DomainDataStructure is not available, IRuleProvider.BuildAsync has to be called in order to call DomainParser.Parse() method." |
@merijndejonge @FlorianHockmann @bkarakaya01 If we call the creation logic in the For example, we lose the option of canceling the process via the CancellationToken. We also cannot ensure that the process was successful. What would you expect in these cases? namespace Nager.PublicSuffix.RuleProviders
{
/// <summary>
/// BaseRuleProvider
/// </summary>
public abstract class BaseRuleProvider : IRuleProvider
{
/// <summary>
/// Parsed public suffix list rules
/// </summary>
protected DomainDataStructure? _domainDataStructure;
public BaseRuleProvider()
{
this.BuildAsync(ignoreCache: false).ConfigureAwait(false).GetAwaiter().GetResult();
} |
I'm aware of the situation here, but there should be a way to force the developer to call the related methods and ensure that build was success. Maybe we should discuss on this. |
I would, in general, not do complex things in a constructor. I think that is against good coding practice. As a result, users of the domain parser don't need to interact directly with the rule provider. Dealing with cancelation tokens and/or error handling can also be handled by the domain parser. |
In order to make use of DomainParser the rule provider it consumes must be initialised by calling the Build() method or else an exception is thrown (DomainDataStructure is not available).
In order to call the Build() method in an aspnet context, some specific, non standard code needs to be executed in the startup class, which, as a side effect, requires that dependencies have to be registered as singleton. When rule providers are more advanced than the ones provided this github repo, for instance when data bases are involved, this may lead to a far from optimal setup.
Why is the Build() method not called by the DomainParser class. That is, rather than throwing an exception when _ruleProvider.GetDomainDataStructure() returns null, why not calling _ruleProvider.Build()?
I offer my help to discuss the design to see if it can be improved for more advance usage scenarios.
The text was updated successfully, but these errors were encountered: